ไม่สามารถเลื่อนไปที่ด้านบนของรายการ flex ที่ล้นคอนเทนเนอร์ได้


259

ดังนั้นในการพยายามทำ modal ที่มีประโยชน์โดยใช้ flexbox ฉันพบสิ่งที่น่าจะเป็นปัญหาของเบราว์เซอร์และสงสัยว่ามีการแก้ไขหรือวิธีแก้ปัญหาที่รู้จักหรือแนวคิดในการแก้ไข

สิ่งที่ฉันพยายามแก้ไขมีสองด้าน ก่อนอื่นให้นำหน้าต่าง modal กึ่งกลางแนวตั้งซึ่งทำงานตามที่คาดไว้ ที่สองคือการได้รับหน้าต่าง modal เพื่อเลื่อน - ภายนอกดังนั้นหน้าต่าง modal ทั้งหมดเลื่อนไม่เนื้อหาภายใน (นี่คือเพื่อให้คุณสามารถมีแบบเลื่อนลงและองค์ประกอบ UI อื่น ๆ ที่สามารถขยายนอกขอบเขตของ modal - เช่นเครื่องมือเลือกวันที่ที่กำหนดเอง ฯลฯ )

อย่างไรก็ตามเมื่อรวมการจัดกึ่งกลางแนวตั้งกับแถบเลื่อนด้านบนของ modal อาจไม่สามารถเข้าถึงได้เมื่อเริ่มล้น ในตัวอย่างข้างต้นคุณสามารถปรับขนาดเพื่อบังคับโอเวอร์โฟลว์และในการทำเช่นนั้นจะช่วยให้คุณเลื่อนไปที่ด้านล่างของคำกริยา แต่ไม่ไปด้านบน (ย่อหน้าแรกถูกตัดออก)

นี่คือลิงค์ไปยังตัวอย่างโค้ด (ง่ายมาก)

https://jsfiddle.net/dh9k18k0/2/

.modal-container {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background: rgba(0, 0, 0, 0.5);
  overflow-x: auto;
}
.modal-container .modal-window {
  display: -ms-flexbox;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  // Optional support to confirm scroll behavior makes sense in IE10
  //-ms-flex-direction: column;
  //-ms-flex-align: center;
  //-ms-flex-pack: center;
  height: 100%;
}
.modal-container .modal-window .modal-content {
  border: 1px solid #ccc;
  border-radius: 4px;
  background: #fff;
  width: 100%;
  max-width: 500px;
  padding: 10px
}

เอฟเฟกต์นี้ (ปัจจุบัน) Firefox, Safari, Chrome และ Opera .. มันน่าสนใจที่จะทำงานอย่างถูกต้องใน IE10 ถ้าคุณแสดงความคิดเห็นใน IE10 vender prefixed css - ฉันยังไม่ได้ทำการทดสอบใน IE11 เลย แต่ถือว่าพฤติกรรมตรงกับ IE10 .

ความคิดใด ๆ จะดี ลิงก์ไปยังปัญหาที่ทราบหรือการให้เหตุผลเบื้องหลังพฤติกรรมนี้ก็มีประโยชน์เช่นกัน

คำตอบ:


478

ปัญหา

Flexbox ทำให้การอยู่ตรงกลางเป็นเรื่องง่ายมาก

โดยเพียงแค่การใช้align-items: centerและjustify-content: centerการภาชนะดิ้นดิ้นรายการ (s) จะเป็นในแนวตั้งและแนวนอนแน่นิ่ง

อย่างไรก็ตามมีปัญหากับวิธีนี้เมื่อรายการ flex มีขนาดใหญ่กว่า flex container

ตามที่ระบุไว้ในคำถามเมื่อรายการ flex ล้นคอนเทนเนอร์ด้านบนจะไม่สามารถเข้าถึงได้

ป้อนคำอธิบายรูปภาพที่นี่

สำหรับการโอเวอร์โฟลว์ในแนวนอนส่วนด้านซ้ายจะเข้าไม่ถึง (หรือส่วนขวาในภาษา RTL)

นี่คือตัวอย่างของคอนเทนเนอร์ LTR ที่มีjustify-content: centerและรายการ flex สามรายการ:

ป้อนคำอธิบายรูปภาพที่นี่

ดูที่ด้านล่างของคำตอบนี้สำหรับคำอธิบายของพฤติกรรมนี้


โซลูชัน # 1

เพื่อแก้ไขปัญหานี้ใช้flexbox อัตรากำไรอัตโนมัติjustify-contentแทน

ด้วยautoระยะขอบรายการเฟล็กที่ล้นจะสามารถอยู่ตรงกลางในแนวตั้งและแนวนอนโดยไม่สูญเสียการเข้าถึงส่วนใด ๆ ของมัน

ดังนั้นแทนที่จะเป็นรหัสนี้ใน flex container:

#flex-container {
    align-items: center;
    justify-content: center;
}

ใช้รหัสนี้ในรายการ flex:

.flex-item {
    margin: auto;
}

ป้อนคำอธิบายรูปภาพที่นี่

ปรับปรุงการสาธิต


โซลูชัน # 2 (ยังไม่ได้ติดตั้งในเบราว์เซอร์ส่วนใหญ่)

เพิ่มsafeมูลค่าให้กับกฎการจัดตำแหน่งคำหลักของคุณเช่นนี้:

justify-content: safe center

หรือ

align-self: safe center

จากสเปคโมดูลการจัดตำแหน่งกล่อง CSS :

4.4 การจัดตำแหน่งล้น: safeและunsafeคำหลักและขีดจำกัดความปลอดภัยในการเลื่อน

เมื่อ [flex item] ใหญ่กว่า [flex container] มันจะล้น โหมดการจัดตำแหน่งบางโหมดหากได้รับเกียรติในสถานการณ์นี้อาจทำให้ข้อมูลสูญหาย: ตัวอย่างเช่นหากเนื้อหาของแถบด้านข้างอยู่กึ่งกลางเมื่อพวกเขาล้นพวกเขาอาจส่งส่วนหนึ่งของกล่องผ่านขอบเริ่มต้นของวิวพอร์ตซึ่งไม่สามารถเลื่อนไป .

เพื่อควบคุมสถานการณ์นี้สามารถระบุโหมดการจัดตำแหน่งโอเวอร์โฟลว์ได้อย่างชัดเจน Unsafeการจัดตำแหน่งให้เกียรติโหมดการจัดตำแหน่งที่ระบุในสถานการณ์ล้นแม้ว่ามันจะทำให้เกิดการสูญเสียข้อมูลในขณะที่safeการจัดตำแหน่งเปลี่ยนโหมดการจัดตำแหน่งในสถานการณ์ล้นในความพยายามที่จะหลีกเลี่ยงการสูญเสียข้อมูล

พฤติกรรมเริ่มต้นคือการมีเรื่องการจัดตำแหน่งภายในพื้นที่ที่เลื่อนได้แม้ว่าในขณะที่เขียนคุณสมบัติความปลอดภัยนี้ยังไม่ได้ดำเนินการ

safe

หากขนาดของ [flex item] ล้น [flex container] เกิน [flex item] จะถูกจัดตำแหน่งแทนราวกับว่าโหมดการจัดตำแหน่งเป็น [ flex-start]

unsafe

โดยไม่คำนึงถึงขนาดสัมพัทธ์ของ [flex item] และ [flex container] ค่าการจัดตำแหน่งที่กำหนดจะถูกให้เกียรติ

หมายเหตุ: โมดูลการจัดตำแหน่งกล่องมีไว้สำหรับการใช้งานในรูปแบบกล่องหลายแบบไม่ใช่แค่งอเท่านั้น ดังนั้นในข้อความที่ตัดตอนมาด้านบนคำในวงเล็บจะพูดว่า "หัวเรื่องการจัดตำแหน่ง", "คอนเทนเนอร์จัดตำแหน่ง" และ " start" ฉันใช้คำเฉพาะแบบดิ้นเพื่อให้ความสนใจกับปัญหาเฉพาะนี้


คำอธิบายสำหรับการ จำกัด การเลื่อนจาก MDN:

ข้อพิจารณาในการยืดหยุ่นของรายการ

คุณสมบัติการจัดตำแหน่งของ Flexbox ทำกึ่งกลาง "จริง" ไม่เหมือนกับวิธีการจัดกึ่งกลางอื่น ๆ ใน CSS ซึ่งหมายความว่ารายการเฟล็กซ์จะยังคงอยู่กึ่งกลางแม้ว่ามันจะล้นคอนเทนเนอร์เฟล็กซ์ก็ตาม

บางครั้งสิ่งนี้อาจเป็นปัญหาได้หากพวกเขาล้นขอบด้านบนของหน้าหรือขอบด้านซ้าย [... ] เนื่องจากคุณไม่สามารถเลื่อนไปที่พื้นที่นั้นแม้ว่าจะมีเนื้อหาอยู่ที่นั่น!

ในรุ่นอนาคตคุณสมบัติการจัดตำแหน่งจะถูกขยายเพื่อให้มีตัวเลือก "ปลอดภัย" เช่นกัน

สำหรับตอนนี้หากเป็นข้อกังวลคุณสามารถใช้มาร์จิ้นเพื่อให้ได้ศูนย์กลางโดยที่พวกเขาจะตอบกลับด้วยวิธีที่ "ปลอดภัย" และหยุดอยู่ตรงกลางหากพวกเขาล้น

แทนที่จะใช้align-คุณสมบัติเพียงวางautoระยะขอบบนไอเท็มเฟล็กที่คุณต้องการจัดกึ่งกลาง

แทนที่justify-คุณสมบัติให้วางระยะขอบอัตโนมัติไว้ที่ขอบด้านนอกของรายการเฟล็กต์แรกและสุดท้ายในคอนเทนเนอร์เฟล็กซ์

autoอัตรากำไรขั้นต้นจะ "ดิ้น" และถือว่าพื้นที่เหลือศูนย์กลางรายการดิ้นเมื่อมีเหลือพื้นที่และเปลี่ยนไปใช้การจัดตำแหน่งปกติเมื่อไม่

อย่างไรก็ตามหากคุณพยายามแทนที่justify-contentด้วยการจัดกึ่งกลางตามขอบในเฟล็กบ็อกซ์แบบหลายบรรทัดคุณอาจจะโชคไม่ดีเนื่องจากคุณจำเป็นต้องวางระยะขอบในรายการเฟล็กซ์แรกและสุดท้ายในแต่ละบรรทัด หากคุณไม่สามารถคาดการณ์ล่วงหน้าว่ารายการใดจะสิ้นสุดลงในบรรทัดใดคุณไม่สามารถใช้การจัดกึ่งกลางตามขอบในแกนหลักได้อย่างน่าเชื่อถือเพื่อแทนที่justify-contentคุณสมบัติ


4
ใช่นั่นเป็นทางออกที่ดีกว่าและขอขอบคุณสำหรับการให้ข้อมูลเชิงลึกที่มีค่าเพิ่มเติม
jejacks0n

1
ควรสังเกตว่าไม่ทำงานใน IE11 พื้นหลังจะถูกตัดออก
Daniel

2
@ แดเนียลฉันเพิ่งทดสอบรหัสใน IE11 ไม่มีอะไรที่ไม่สามารถเข้าถึงได้ ในความเป็นจริงปัญหาที่อธิบายในคำถามไม่ได้มีอยู่ใน IE11 คุณอาจอ้างถึงข้อความล้นที่เกิดขึ้นใน IE11 เท่านั้น นั่นเป็นอีกปัญหาหนึ่งสำหรับคำถามอื่น
Michael Benjamin

11
ในการแก้ไขปัญหาใน IE11: เพิ่มalign-items: flex-startใน flex container และเก็บไว้margin: autoสำหรับรายการ flex
Eugene Fidelin

2
สิ่งนี้ไม่ทำงานสำหรับฉันเมื่อใช้ flex-direction: column;
สเตฟาน

22

ตามกฎของเมอร์ฟีแล้วการอ่านที่ฉันทำหลังจากโพสต์คำถามนี้ทำให้เกิดผลลัพธ์บางอย่าง - ไม่ได้รับการแก้ไขอย่างสมบูรณ์ แต่มีประโยชน์บ้าง

ฉันเล่นกับความสูงขั้นต่ำเล็กน้อยก่อนโพสต์ แต่ไม่ทราบถึงข้อ จำกัด ในการปรับขนาดที่ค่อนข้างใหม่สำหรับสเป็ค

http://caniuse.com/#feat=intrinsic-width

การเพิ่มmin-height: min-contentลงในพื้นที่ flexbox จะช่วยแก้ไขปัญหาใน Chrome และด้วยคำนำหน้าผู้ขายยังแก้ไข Opera และ Safari แม้ว่า Firefox จะยังไม่ได้รับการแก้ไข

min-height: -moz-min-content; // not implemented
min-height: -webkit-min-content // works for opera and safari
min-height: min-content // works for chrome

ยังคงมองหาแนวคิดใน Firefox และวิธีแก้ปัญหาที่เป็นไปได้อื่น ๆ


ฉันแค่อยากจะบอกว่ามันใช้งานได้แล้วสำหรับฉันใน Firefox ดังนั้นการแก้ปัญหาด้วยเนื้อหาขั้นต่ำจึงสมบูรณ์แบบ
pudgereyem

@pudgereyem ฉันคิดว่าพวกเขาใช้งานแล้ว โซลูชันอื่นที่margin: autoหยุดflex-basisทำงานกับฉันในขณะที่คำตอบนี้แก้ปัญหาทั้งสองได้
Martin Dawson

ทางออกที่ยอดเยี่ยมแน่นอน ฉันไม่สนใจเกี่ยวกับ Edge หรือ IE ดังนั้นจึงเหมาะกับฉัน!
Ohgodwhy

18

ฉันจัดการเพื่อดึงสิ่งนี้ออกด้วยเพียง 3 ตู้คอนเทนเนอร์ เคล็ดลับคือการแยกคอนเทนเนอร์ flexbox ออกจากคอนเทนเนอร์ที่ควบคุมการเลื่อน สุดท้ายใส่ทุกอย่างลงในรูทคอนเทนเนอร์เพื่อจัดกึ่งกลางทั้งหมด นี่คือสไตล์ที่สำคัญในการสร้างเอฟเฟกต์:

CSS:

.root {
  display: flex;
  justify-content: center;
  align-items: center;
}

.scroll-container {
  margin: auto;
  max-height: 100%;
  overflow: auto;
}

.flex-container {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

HTML:

<div class="root">
  <div class="scroll-container">
    <div class="flex-container">
      <p>Lorem ipsum dolor sit amet.</p>
    </div>
  </div>
</div>

ฉันได้สร้างตัวอย่างที่นี่: https://jsfiddle.net/r5jxtgba/14/


ขอบคุณสำหรับเคล็ดลับการเลื่อนภาชนะฉันค้นหาตั้งแต่สองวันสำหรับการแก้ไขเนื้อหาเลื่อนของฉัน ***** !!!
artSx

จำ dont ให้กับflex: 1 1 auto scroll-containerฉันทำสิ่งนี้ด้วยนิสัยและมีปัญหา
AmirHossein

1
jsfiddle แสดงว่ามันไม่ทำงานเมื่อคุณเพิ่มเนื้อหาภายในคอนเทนเนอร์
bplittle

4

ฉันคิดว่าฉันพบวิธีแก้ปัญหา จะทำงานร่วมกับจำนวนของข้อความและข้อความสั้นคุณไม่จำเป็นต้องระบุความกว้างของสิ่งใด ๆ และควรทำงานใน IE8

.wrap1 {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background: rgba(0, 0, 0, 0.5);
  overflow-y: auto;
}
.wrap2 {
  display: table;
  width: 100%;
  height: 100%;
  text-align: center;
}
.wrap3 {
  vertical-align: middle;
  display: table-cell;
}
.wrap4 {
  margin: 10px;
}
.dialog {
  text-align: left;
  background-color: white;
  padding: 5px;
  border-radius: 3px;
  margin: auto;
  display: inline-block;
  box-shadow: 2px 2px 4px rgba(0, 0, 0, .5);
}
<div class="wrap1">
  <div class="wrap2">
    <div class="wrap3">
      <div class="wrap4">
        <div class="dialog">
          <p>Lorem ipsum dolor sit amet.</p>
        </div>
      </div>
    </div>
  </div>
</div>


นี่เป็นทางออกที่ดีที่สุดสำหรับเบราว์เซอร์รุ่นเก่า ขอบคุณมาก!
Daniel

5
ว้าวนั่นมันห่อมาก
Nathan Arthur

1
ว้าวฉันใช้เวลาหลายชั่วโมงเพื่อที่จะทำสิ่งนี้ให้สำเร็จ (วิธีการอื่น ๆ ทั้งหมดล้มเหลวในมือถือ Chrome เมื่อคุณเพิ่มแอนิเมชั่นมันไม่ได้) ขอบคุณมาก ๆ !
falsePockets

1

ตาม MDN ที่safeคุ้มค่าสามารถตอนนี้จะให้คุณสมบัติเหมือนและalign-items justify-contentมันอธิบายดังนี้

ถ้าขนาดของรายการที่ล้นภาชนะจัดตำแหน่ง, startรายการที่สอดคล้องแทนเช่นถ้าโหมดการจัดตำแหน่งได้

ดังนั้นมันอาจจะใช้ดังนี้

.rule
{
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: safe center;
}

อย่างไรก็ตามมันยังไม่ชัดเจนว่ารองรับเบราว์เซอร์ได้มากแค่ไหนฉันไม่สามารถหาตัวอย่างการใช้งานได้และฉันมีปัญหาบางอย่างกับตัวเอง กล่าวถึงที่นี่เพื่อดึงดูดความสนใจมากขึ้น


7 มิถุนายน 2018 และยังไม่ได้ใช้งานในโครเมี่ยม
AmirHossein

ตามหน้า MDN (ปัจจุบัน) "ปลอดภัย" และ "ไม่ปลอดภัย" ยังคงเป็น Firefox เท่านั้น ณ จุดนี้ (เช่น Safari และเบราว์เซอร์มือถือส่วนใหญ่มีการสนับสนุนที่ไม่รู้จัก - ฉันจะเล่นอย่างปลอดภัยและไม่สนับสนุน)
JaMiT

MDN รายงานการสนับสนุน Firefox แต่เมื่อฉันทดสอบใน Firefox ดูเหมือนว่าจะไม่ทำงาน jsbin.com/pimoqof/1/edit?html,css,output
Oliver Joseph Ash

มิถุนายน 2020 และไม่ได้อยู่ในเบราว์เซอร์ส่วนใหญ่ตาม caniuse
den232

0

ฉันยังจัดการทำได้โดยใช้คอนเทนเนอร์พิเศษ

HTML

<div class="modal-container">
  <div class="modal">
    <div class="content-container">
       <div class="content">
         <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
        </div>
      </div>
  </div>  
</div>

CSS

.modal-container {
  display: flex;
  justify-content: center;
  align-items: center;
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background-color: black;
}

.modal {
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #aaa;
  height: 80%;
  width: 90%;
}

.content-container {
  background-color: blue;
  max-height: 100%;
  overflow: auto;
  padding:0;
}

.content {
  display: flex;
  background-color: red;
  padding: 5px;
  width: 900px;
  height: 300px;
}

ใน jsfiddle> https://jsfiddle.net/Nash171/cpf4weq5/

เปลี่ยนค่าความกว้าง / ความสูงของเนื้อหาและดู


0

2 วิธี Flex Container พร้อม Table fallback ทดสอบ IE8-9, flex ทำงานใน IE10,11 แก้ไข: แก้ไขเพื่อให้แน่ใจว่าอยู่ตรงกลางแนวตั้งเมื่อเนื้อหาน้อยที่สุดเพิ่มการสนับสนุนแบบดั้งเดิม

ปัญหานี้เกิดจากความสูงที่สืบทอดมาจากขนาดวิวพอร์ตซึ่งทำให้เด็กล้นตามที่ Michael ตอบ https://stackoverflow.com/a/33455342/3500688

สิ่งที่ง่ายขึ้นและใช้ flex เพื่อรักษาเค้าโครงภายในคอนเทนเนอร์ป๊อปอัพ (เนื้อหา):

#popup {
position: fixed;
top: 0;
left: 0;
right: 0;
min-height: 100vh;
background-color: rgba(0,0,0,.25);
margin: auto;
overflow: auto;
height: 100%;
bottom: 0;
display: flex;
align-items: flex-start;
box-sizing:border-box;
padding:2em 20px;
}
.container {
background-color: #fff;
margin: auto;
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
/* width: 100%; */
max-width: 500px;
padding: 10px;
    /* display: flex; */
    /* flex-wrap: wrap; */
}
		<!--[if lt IE 10]>
<style>
	  #popup {
			display: table;
			width:100%;
		}
		.iewrapper {
			display: table-cell;
			vertical-align: middle;
		}
	</style>
	<![endif]-->
<div id="popup">
	<!--[if lt IE 10]>
<div class="iewrapper">
<![endif]-->
    <div class="container">
        <p class="p3">Test</p>
    <p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
    <p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
    </div>
	<!--[if lt IE 10]>
<div class="iewrapper">
<![endif]-->
</div>

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.