flexbox 항목이 열 모드로 줄 바꿈 될 때 컨테이너의 너비가 커지지 않습니다 너비가 커져야합니다. 이 너비 증가는

중첩 된 flexbox 레이아웃을 작업 중이며 다음과 같이 작동합니다.

가장 바깥 쪽 레벨 ( ul#main)은 더 많은 항목이 추가 될 때 오른쪽으로 확장되어야하는 가로 목록입니다. 너무 커지면 가로 스크롤 막대가 있어야합니다.

#main {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    overflow-x: auto;
    /* ...and more... */
}

이 목록 ( ul#main > li) 의 각 항목 에는 헤더 ( ul#main > li > h2)와 내부 목록 ( ul#main > li > ul.tasks)이 있습니다. 이 내부 목록은 수직이므로 필요할 때 열로 줄 바꿈해야합니다. 더 많은 열을 감쌀 때 더 많은 항목을 넣을 공간을 만들기 위해 너비가 커져야합니다. 이 너비 증가는 외부 목록의 포함 항목에도 적용되어야합니다.

.tasks {
    flex-direction: column;
    flex-wrap: wrap;
    /* ...and more... */
}

내 문제는 창의 높이가 너무 작아지면 내부 목록이 줄 바꿈되지 않는다는 것입니다. CSS-Tricks 의 지침을 꼼꼼하게 따르려고 노력하면서 모든 플렉스 속성을 많이 변경하려고 시도 했지만 운이 없습니다.

JSFiddle 은 지금까지 내가 가지고있는 것을 보여줍니다.

예상 결과 (내가 원하는 것) :

내가 원하는 출력

실제 결과 (내가 얻은 것) :

내 현재 출력

이전 결과 (2015 년에 얻은 것) :

내 오래된 출력

최신 정보

약간의 조사가 끝나면 더 큰 문제처럼 보이기 시작합니다. 모든 주요 브라우저는 동일한 방식으로 작동하며 내 flexbox 디자인과 중첩되지 않습니다. 더 간단한 flexbox 열 레이아웃조차도 항목을 줄 바꿈 할 때 목록의 너비를 늘리지 않습니다.

다른 JSFiddle 은 문제를 분명히 보여줍니다. 현재 버전의 Chrome, Firefox 및 IE11에서는 모든 항목이 올바르게 줄 바꿈됩니다. 목록의 높이는 row모드에서 증가 하지만 너비는 column모드 에서 증가하지 않습니다 . 또한 column모드 의 높이를 변경할 때 요소가 즉시 리플 로우되지 않지만 row모드가 있습니다.

그러나 공식 사양 (특히 예 5 참조) 은 내가하고 싶은 일이 가능해야 함을 나타내는 것으로 보입니다.

누군가이 문제에 대한 해결 방법을 제안 할 수 있습니까?

업데이트 2

크기 조정 이벤트 중에 다양한 요소의 높이와 너비를 업데이트하기 위해 JavaScript를 사용하여 많은 실험을 한 후에는 너무 복잡하고 그렇게 해결하기가 너무 어렵다는 결론에 도달했습니다. 또한 JavaScript를 추가하면 flexbox 모델이 깨져서 최대한 깨끗하게 유지해야합니다.

지금 은 내부 컨테이너가 필요할 때 세로로 스크롤되도록 overflow-y: auto대신에 넘어갑니다 flex-wrap: wrap. 예쁘지는 않지만 최소한 사용성을 크게 손상시키지 않는 한 가지 방법입니다.



답변

문제

이것은 플렉스 레이아웃의 근본적인 결함처럼 보입니다.

열 방향의 플렉스 컨테이너는 추가 열을 수용하도록 확장되지 않습니다. (이 문제는 아닙니다 flex-direction: row.)

이 질문은 CSS에서 명확한 대답없이 여러 번 요청되었습니다 (아래 목록 참조).

이 문제는 모든 주요 브라우저에서 발생하기 때문에 버그로 고정하기가 어렵습니다. 그러나 그것은 질문을 제기합니다 :

모든 주요 브라우저가 줄 방향으로 랩에서 열 방향이 아닌 플렉스 컨테이너를 확장 할 수 있습니까?

당신은 그들 중 적어도 하나가 그것을 올바르게 얻을 것이라고 생각할 것입니다. 나는 그 이유에 대해서만 추측 할 수 있습니다. 기술적으로 어려운 구현 일 수도 있고이 반복을 위해 보류 된 것일 수도 있습니다.

업데이트 : 이 문제는 Edge v16에서 해결 된 것으로 보입니다.


문제의 예

OP는 문제를 보여주는 유용한 데모를 만들었습니다. 여기에 복사하고 있습니다 : http://jsfiddle.net/nwccdwLw/1/


해결 방법 옵션

Stack Overflow 커뮤니티의 해키 솔루션 :


추가 분석


같은 문제를 설명하는 다른 게시물


답변

파티에 늦었지만 나중에이 문제가 계속 발생했습니다. 그리드를 사용하여 솔루션을 찾았습니다. 컨테이너에서 사용할 수 있습니다

display: grid;
grid-auto-flow: column;
grid-template-rows: repeat(6, auto);

FlexPen 문제와 그리드 수정 사이를 전환하는 CodePen의 예가 있습니다. https://codepen.io/MandeeD/pen/JVLdLd


답변

많은 주요 브라우저가 수년 후에이 버그로 고통받는 것은 유감입니다. 자바 스크립트 해결 방법을 고려하십시오. 브라우저 창의 크기가 조정되거나 컨텐츠가 요소에 추가 될 때마다이 코드를 실행하여 적절한 너비로 크기를 조정하십시오. 프레임 워크에서 지시문을 정의하여이를 수행 할 수 있습니다.

    element.style.flexBasis = "auto";
    element.style.flexBasis = `${element.scrollWidth}px`;


답변

방금 여기서 멋진 PURE CSS 해결 방법을 찾았습니다.

https://jsfiddle.net/gcob492x/3/

까다로운 : writing-mode: vertical-lr목록 div에서 설정 한 다음 writing-mode: horizontal-tb목록 항목에서 설정하십시오. JSFiddle에서 스타일을 조정해야했습니다 (솔루션에 필요하지 않은 많은 정렬 스타일을 제거하십시오).

참고 : 의견에 따르면 Firefox가 아닌 Chromium 기반 브라우저에서만 작동합니다. Chrome에서만 개인적으로 테스트했습니다. 다른 브라우저에서 작동하도록 수정하거나 다른 브라우저에서 작동하도록하는 방법이있을 수 있습니다.

이 의견에 대한 큰 소리 : flexbox 항목이 열 모드로 줄 바꿈되면 컨테이너의 너비가 커지지 않습니다 . 이 문제 스레드 를 파헤쳐 서 https://bugs.chromium.org/p/chromium/issues/detail?id=507397#c39로 연결되어이 JSFiddle로 연결되었습니다.


답변

해결책이나 적절한 해결 방법이 아직 제안되지 않았으므로 약간 다른 접근 방식으로 요청 된 동작을 얻을 수있었습니다. 레이아웃을 3 개의 다른 div로 분리하는 대신 모든 항목을 1 div에 추가하고 사이에 더 많은 div가있는 분리를 만듭니다.

제안 된 솔루션은 3 개의 섹션이 있다고 가정하지만 하드 코딩되어 있지만 일반적인 섹션으로 확장 될 수 있습니다. 주요 아이디어는이 레이아웃을 어떻게 달성 할 수 있는지 설명하는 것입니다.

  1. flex를 사용하여 항목을 감싸는 하나의 컨테이너 div에 모든 항목 추가
  2. 각 “내부 컨테이너”의 첫 번째 항목 (섹션이라고 함)에는 클래스가 있으며,이를 통해 각 섹션의 분리 및 스타일을 만드는 조작을 수행 할 수 있습니다.
  3. :before각 첫 번째 항목을 사용하여 각 섹션의 제목을 찾을 수 있습니다.
  4. 를 사용 space하면 섹션 사이에 간격이 생깁니다
  5. 는 이후 space나는 또한 추가 해요 섹션의 전체 높이 포함되지 않습니다 :after절대 위치 및 흰색 배경으로 위치하도록 섹션을.
  6. 각 섹션의 배경색을 스타일 지정하려면 각 섹션의 첫 번째 항목 안에 다른 div를 추가합니다. 나는 또한 절대적 입장을 가지고있을 것이다 z-index: -1.
  7. 각 배경의 올바른 너비를 얻으려면 JS를 사용하고 올바른 너비를 설정하고 크기를 조정할 리스너를 추가합니다.
function calcWidth() {
  var size = $(document).width();
  var end = $(".end").offset().left;

  var todoWidth = $(".doing-first").offset().left;
  $(".bg-todo").css("width", todoWidth);

  var doingWidth = $(".done-first").offset().left - todoWidth;
  $(".bg-doing").css("width", doingWidth);

  var doneWidth = $(".end").offset().left - $(".done-first").offset().left;
  $(".bg-done").css("width", doneWidth + 20);

}

calcWidth();

$(window).resize(function() {
  calcWidth();
});
.container {
  display: flex;
  flex-wrap: wrap;
  flex-direction: column;
  height: 120px;
  align-content: flex-start;
  padding-top: 30px;
  overflow-x: auto;
  overflow-y: hidden;
}

.item {
  width: 200px;
  background-color: #e5e5e5;
  border-radius: 5px;
  height: 20px;
  margin: 5px;
  position: relative;
  box-shadow: 1px 1px 5px 0px rgba(0, 0, 0, 0.75);
  padding: 5px;
}

.space {
  height: 150px;
  width: 10px;
  background-color: #fff;
  margin: 10px;
}

.todo-first:before {
  position: absolute;
  top: -30px;
  height: 30px;
  content: "To Do (2)";
  font-weight: bold;
}

.doing-first:before {
  position: absolute;
  top: -30px;
  height: 30px;
  content: "Doing (5)";
  font-weight: bold;
}

.doing-first:after,
.done-first:after {
  position: absolute;
  top: -35px;
  left: -25px;
  width: 10px;
  height: 180px;
  z-index: 10;
  background-color: #fff;
  content: "";
}

.done-first:before {
  position: absolute;
  top: -30px;
  height: 30px;
  content: "Done (3)";
  font-weight: bold;
}

.bg-todo {
  position: absolute;
  background-color: #FFEFD3;
  width: 100vw;
  height: 150px;
  top: -30px;
  left: -10px;
  z-index: -1;
}

.bg-doing {
  position: absolute;
  background-color: #EFDCFF;
  width: 100vw;
  height: 150px;
  top: -30px;
  left: -15px;
  z-index: -1;
}

.bg-done {
  position: absolute;
  background-color: #DCFFEE;
  width: 10vw;
  height: 150px;
  top: -30px;
  left: -15px;
  z-index: -1;
}

.end {
  height: 150px;
  width: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">

  <div class="item todo-first">
    <div class="bg-todo"></div>
    Drink coffee
  </div>
  <div class="item">Go to work</div>

  <div class="space"></div>

  <div class="item doing-first">
    <div class="bg-doing"></div>
    1
  </div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>

  <div class="space"></div>

  <div class="item done-first">
    <div class="bg-done"></div>
    1
  </div>
  <div class="item">2</div>
  <div class="item">3</div>

  <div class="end"></div>

</div>


답변

가능한 JS 솔루션 ..

var ul = $("ul.ul-to-fix");

if(ul.find("li").length>{max_possible_rows)){
    if(!ul.hasClass("width-calculated")){
        ul.width(ul.find("li").eq(0).width()*ul.css("columns"));
        ul.addClass("width-calculated");
     }
}


답변