컨테이너가 넘쳐나는 플렉스 아이템의 맨 위로 스크롤 할 수 없습니다


259

따라서 flexbox를 사용하여 유용한 모달을 만들려고 할 때 브라우저 문제인 것으로 보였으며 알려진 수정 또는 해결 방법 또는 해결 방법에 대한 아이디어가 있는지 궁금합니다.

내가 해결하려고하는 것은 두 가지 측면이 있습니다. 먼저 모달 창을 세로로 가운데에 놓으면 예상대로 작동합니다. 두 번째는 모달 창을 스크롤하는 것입니다-외부에서 모달 창 전체의 내용이 아닌 전체 모달 창을 스크롤합니다 (이렇게하면 모달의 범위를 벗어나 확장 할 수있는 드롭 다운 및 기타 UI 요소를 가질 수 있음) 맞춤 날짜 선택기 등)

그러나 수직 중심과 스크롤 막대를 결합 할 때 모달 상단이 오버플로되기 시작하여 액세스 할 수 없게됩니다. 위의 예에서, 오버 플로우를 강제로하기 위해 크기를 조정할 수 있으며, 그렇게하면 모달의 맨 아래로 스크롤 할 수 있지만 맨 위로는 스크롤 할 수 없습니다 (첫 번째 단락은 잘림).

다음은 예제 코드에 대한 링크입니다 (매우 단순화 됨).

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 벤더 접두사 CSS로 주석을 달면 IE10에서 흥미롭게 올바르게 작동합니다 .IE11에서는 테스트를 귀찮게하지 않았지만 IE10의 동작과 일치한다고 가정합니다. .

어떤 아이디어라도 좋을 것입니다. 알려진 문제에 대한 링크 또는이 동작의 이유도 유용합니다.

답변:


478

문제

Flexbox는 센터링을 매우 쉽게 만듭니다.

Flex 컨테이너 를 간단히 적용 align-items: center하고 justify-content: centerFlex 컨테이너에 적용하면 Flex 품목이 수직 및 수평 중앙에 배치됩니다.

그러나, 플렉스 아이템이 플렉스 컨테이너보다 크면이 방법에 문제가있다.

문제에서 언급했듯이, 플렉스 아이템이 컨테이너를 넘치면 상단에 액세스 할 수 없게됩니다.

여기에 이미지 설명을 입력하십시오

수평 오버플로의 경우 왼쪽 섹션에 액세스 할 수 없게됩니다 (또는 RTL 언어의 오른쪽 섹션).

다음은 justify-content: center3 개의 flex 항목 이있는 LTR 컨테이너의 예입니다 .

여기에 이미지 설명을 입력하십시오

이 동작에 대한 설명은이 답변의 맨 아래를 참조하십시오.


해결책 # 1

이 문제를 해결하려면 대신 flexbox 자동 여백 을 사용하십시오 justify-content.

auto여백, 넘쳐 플렉스 항목은 수직 및 수평의 어떤 부분에 대한 액세스를 잃지 않고 중심을 할 수 있습니다.

따라서 플렉스 컨테이너 에서이 코드 대신 :

#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. 오버 플로우 정렬 : safeunsafe키워드 및 스크롤 안전 한계

[flex item]이 [flex container]보다 크면 오버플로됩니다. 예를 들어, 사이드 바의 내용이 중앙에 오면 넘치면 상자의 일부를 뷰포트의 시작 가장자리를 지나서 스크롤 할 수없는 일부 부분을 보낼 수 있습니다. .

이 상황을 제어하기 위해 오버 플로우 정렬 모드를 명시 적으로 지정할 수 있습니다. Unsafe정렬은 데이터 손실을 유발하더라도 오버플로 상황에서 지정된 정렬 모드를 유지하는 반면, safe정렬 은 데이터 손실 을 피하기 위해 오버플로 상황에서 정렬 모드를 변경합니다.

기본 동작은 스크롤 가능 영역 내에 정렬 주제를 포함하는 것입니다. 그러나이 안전 기능을 작성할 때는 아직 구현되지 않았습니다.

safe

[flex 항목]의 크기가 [flex 컨테이너]를 초과하면 정렬 모드가 [ flex-start] 인 것처럼 [flex 항목]이 대신 정렬됩니다 .

unsafe

[flex item] 및 [flex container]의 상대적 크기에 관계없이 주어진 정렬 값이 적용됩니다.

참고 : Box Alignment Module은 플렉스뿐만 아니라 여러 박스 레이아웃 모델에서도 사용할 수 있습니다. 따라서 위의 발췌 부분에서 괄호 안의 용어는 실제로 "정렬 제목", "정렬 컨테이너"및 " start"입니다. 나는이 특정 문제에 계속 초점을 맞추기 위해 플렉스 특정 용어를 사용했습니다.


MDN의 스크롤 제한에 대한 설명 :

플렉스 아이템 고려 사항

Flexbox의 정렬 속성은 CSS의 다른 센터링 방법과 달리 "진정한"센터링을 수행합니다. 이것은 플렉스 아이템이 플렉스 컨테이너에 넘치더라도 플렉스 아이템이 중앙에 유지된다는 것을 의미합니다.

그러나 내용이 있더라도 해당 영역으로 스크롤 할 수 없기 때문에 페이지 상단 가장자리 나 왼쪽 가장자리 [...]를지나 넘치면 문제가 될 수 있습니다.

다음 릴리스에서는 정렬 속성이 "안전한"옵션을 갖도록 확장 될 것입니다.

지금은 이것이 문제가되는 경우 마진을 사용하여 센터링을 수행 할 수 있습니다. 마진은 "안전한"방식으로 응답하고 오버플로가 발생하면 센터링을 중지하므로 센터링을 수행 할 수 있습니다.

align-속성 을 사용하는 대신 가운데 에 auto맞추려는 플렉스 항목 에 여백을 두십시오 .

justify-속성 대신 플렉스 컨테이너에서 첫 번째 및 마지막 플렉스 항목의 바깥 쪽 가장자리에 자동 여백을 둡니다.

auto여백은 "유연"하고 남은 공간을 가정하고, 남은 공간이 있으면 플렉스 항목을 중앙에두고 , 그렇지 않으면 정상 정렬로 전환합니다.

그러나 justify-content여러 줄로 된 flexbox에서 여백 기반의 센터링 으로 교체하려는 경우 각 줄의 첫 번째 및 마지막 flex 항목에 여백을 넣어야하기 때문에 운이 좋지 않을 수 있습니다. 어떤 항목이 어떤 라인에서 끝나는 지 미리 예측할 수 없으면 주축에서 마진 기반 중심을 안정적으로 사용하여 justify-content속성 을 대체 할 수 없습니다 .


4
그렇습니다. 더 나은 솔루션이며 귀중한 통찰력을 제공해 주셔서 감사합니다.
jejacks0n

1
IE11에서는 작동하지 않습니다. 배경이 잘립니다.
Daniel

2
@Daniel, 방금 IE11에서 코드를 테스트했습니다. 접근 할 수있는 것이 없습니다. 실제로, 질문에 설명 된 문제는 IE11에도 존재하지 않습니다. IE11에서만 발생하는 텍스트 오버플로를 참조 할 수 있습니다. 그것은 또 다른 질문에 대한 또 다른 문제입니다.
Michael Benjamin

11
IE11의 문제를 해결하려면 align-items: flex-start플렉스 컨테이너에 추가 하고 margin: auto플렉스 항목을 유지하십시오 .
유진 Fidelin

2
flex-direction : column;을 사용할 때 이것은 작동하지 않습니다.
Stefan

22

머피의 법칙에서 알 수 있듯이이 질문을 게시 한 후 내가 한 결과는 완전히 해결되지는 않았지만 그럼에도 불구하고 다소 유용했습니다.

게시하기 전에 최소 높이로 약간 놀았 지 만 사양에 상당히 새로운 본질적인 크기 제한을 알지 못했습니다.

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

추가 min-height: min-contentflexbox 영역에 를 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/ 데모를 만들었습니다.


스크롤 컨테이너 팁에 대한 thx, 나는 ***** 스크롤 내용을 수정하기 위해 이틀부터 검색했습니다 !!!
artSx

, 망가주고 기억 flex: 1 1 auto받는 사람을 scroll-container. 나는 습관적으로 이것을하고 있었고 문제가 발생했습니다.
AmirHossein 2016 년

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
와우, 나는 이것을 달성하기 위해 몇 시간을 보냈다 . (애니메이션을 추가 할 때 모바일 크롬에서 다른 모든 방법이 실패합니다. 그렇지 않습니다) 감사합니다.
falsePockets

1

MDN에 따르면 safe값은 align-itemsand와 같은 속성에 제공 될 수 있습니다 justify-content. 다음과 같이 설명됩니다.

항목의 크기가 정렬 컨테이너를 오버플로하는 경우 정렬 모드가 마치 것처럼 정렬됩니다 start.

따라서 다음과 같이 사용될 수 있습니다.

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

그러나 브라우저가 얼마나 많은 브라우저를 지원하는지 확실하지 않으며 사용 예를 찾을 수 없으며 자체적으로 문제가 있습니다. 더주의를 끌기 위해 여기에 언급하십시오.


2018 년 6 월 7 일이며 여전히 크롬으로 구현되지 않았습니다.
AmirHossein 2016 년

(현재) MDN 페이지에 따르면이 시점에서 "안전한"및 "안전하지 않은"은 여전히 ​​Firefox 전용입니다 (사파리와 대부분의 모바일 브라우저는 알 수없는 지원을합니다. 안전하다고 생각하며 지원하지 않습니다).
JaMiT

MDN은 Firefox 지원을보고하지만 Firefox에서 테스트했을 때 작동하지 않는 것 같습니다. jsbin.com/pimoqof/1/edit?html,css,output
Oliver Joseph Ash

caniuse에 따르면 2020 년 6 월
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

IE8-9에서 테이블 폴백 테스트를 사용한 2 컨테이너 플렉스 방법, 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.