[css] 높이를 전환하는 방법 : 0; 높이 : 자동; CSS를 사용합니까?

나는 노력하고 있습니다 <ul>CSS 전환을 사용하여 아래 슬라이드 .

에서 <ul>시작합니다 height: 0;. 마우스를 올리면 높이가로 설정됩니다 height:auto;. 그러나 이로 인해 전환이 아닌 단순히 표시됩니다 .

에서에서 height: 40px;를 수행하면을 ( 를 height: auto;) 위로 슬라이드 height: 0;한 다음 갑자기 올바른 높이로 점프합니다.

JavaScript를 사용하지 않고 어떻게 할 수 있습니까?

#child0 {
  height: 0;
  overflow: hidden;
  background-color: #dedede;
  -moz-transition: height 1s ease;
  -webkit-transition: height 1s ease;
  -o-transition: height 1s ease;
  transition: height 1s ease;
}
#parent0:hover #child0 {
  height: auto;
}
#child40 {
  height: 40px;
  overflow: hidden;
  background-color: #dedede;
  -moz-transition: height 1s ease;
  -webkit-transition: height 1s ease;
  -o-transition: height 1s ease;
  transition: height 1s ease;
}
#parent40:hover #child40 {
  height: auto;
}
h1 {
  font-weight: bold;
}
The only difference between the two snippets of CSS is one has height: 0, the other height: 40.
<hr>
<div id="parent0">
  <h1>Hover me (height: 0)</h1>
  <div id="child0">Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>
  </div>
</div>
<hr>
<div id="parent40">
  <h1>Hover me (height: 40)</h1>
  <div id="child40">Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>
  </div>
</div>



답변

max-height전환에 사용 하지 말고 사용하십시오 height. 그리고 값을 설정하십시오.max-height 상자보다 훨씬 큰 하십시오.

참조 JSFiddle이 데모에서는 또 다른 크리스 요르단에서 제공하는 답변을 여기에.

#menu #list {
    max-height: 0;
    transition: max-height 0.15s ease-out;
    overflow: hidden;
    background: #d5d5d5;
}

#menu:hover #list {
    max-height: 500px;
    transition: max-height 0.25s ease-in;
}
<div id="menu">
    <a>hover me</a>
    <ul id="list">
        <!-- Create a bunch, or not a bunch, of li's to see the timing. -->
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
    </ul>
</div>


답변

대신 scaleY를 사용해야합니다.

ul {
  background-color: #eee;
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.26s ease;
}
p:hover ~ ul {
  transform: scaleY(1);
}
<p>Hover This</p>
<ul>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>

jsfiddle 에서 위 코드의 공급 업체 접두사 버전을 만들었고 jsfiddle 을 높이 대신 scaleY를 사용하도록 변경했습니다 .


답변

관련 높이 중 하나가 인 경우 현재 높이에 애니메이션을 적용 할 수 없으므로 auto두 개의 명시 적 높이를 설정해야합니다.


답변

내가 항상 사용했던 것을이 솔루션은 다음 축소, 첫 번째 페이드 아웃이었다 font-size, padding그리고 margin값을. A는 닦아 것과 같습니다 보이지 않지만, 정적없이 작동 height또는 max-height.

작업 예 :

/* final display */
#menu #list {
    margin: .5em 1em;
    padding: 1em;
}

/* hide */
#menu:not(:hover) #list {
    font-size: 0;
    margin: 0;
    opacity: 0;
    padding: 0;
    /* fade out, then shrink */
    transition: opacity .25s,
                font-size .5s .25s,
                margin .5s .25s,
                padding .5s .25s;
}

/* reveal */
#menu:hover #list {
    /* unshrink, then fade in */
    transition: font-size .25s,
                margin .25s,
                padding .25s,
                opacity .5s .25s;
}
<div id="menu">
    <b>hover me</b>
    <ul id="list">
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
    </ul>
</div>

<p>Another paragraph...</p>


답변

나는 이것이이 질문에 대한 서른 뭔가라는 것을 알고 있지만 그만한 가치가 있다고 생각합니다. 이것은 다음과 같은 속성을 가진 CSS 전용 솔루션입니다.

  • 처음에는 지연이 없으며 전환이 일찍 중지되지 않습니다. CSS에서 전환 지속 시간을 300ms로 지정하면 양방향으로 (확장 및 축소) 전환에 300ms의 기간이 걸립니다.
  • 실제 높이를 (과 달리 transform: scaleY(0)) 전환 하므로 접을 수있는 요소 뒤에 내용이 있으면 올바른 작업을 수행합니다.
  • (다른 솔루션에서와 같이) 마법의 숫자 있지만 ( “상자의 길이보다 더 긴 길이를 선택하십시오”) 가정이 잘못되면 치명적이지는 않습니다. 전환은이 경우에 놀라운 보이지 않을 수 있지만, 이전과 전환 후,이 문제가되지 않습니다 : 확장 된 (에서 height: auto당신이 선택하는 경우) 상태, 전체 내용이 항상 (달리 예를 올바른 높이가 max-height밝혀 그 수 너무 낮은). 그리고 접힌 상태에서 높이는 0입니다.

데모

다음은 모두 동일한 CSS를 사용하는 높이가 다른 세 개의 접을 수있는 요소가있는 데모입니다. “스 니펫 실행”을 클릭 한 후 “전체 페이지”를 클릭 할 수 있습니다. JavaScript는 collapsedCSS 클래스 만 토글하므로 측정이 필요하지 않습니다. (확인란 또는을 사용하여 JavaScript없이이 정확한 데모를 수행 할 수 있습니다 :target). 또한 전환을 담당하는 CSS 부분은 매우 짧으며 HTML에는 단일 추가 래퍼 요소 만 필요합니다.

$(function () {
  $(".toggler").click(function () {
    $(this).next().toggleClass("collapsed");
    $(this).toggleClass("toggled"); // this just rotates the expander arrow
  });
});
.collapsible-wrapper {
  display: flex;
  overflow: hidden;
}
.collapsible-wrapper:after {
  content: '';
  height: 50px;
  transition: height 0.3s linear, max-height 0s 0.3s linear;
  max-height: 0px;
}
.collapsible {
  transition: margin-bottom 0.3s cubic-bezier(0, 0, 0, 1);
  margin-bottom: 0;
  max-height: 1000000px;
}
.collapsible-wrapper.collapsed > .collapsible {
  margin-bottom: -2000px;
  transition: margin-bottom 0.3s cubic-bezier(1, 0, 1, 1),
              visibility 0s 0.3s, max-height 0s 0.3s;
  visibility: hidden;
  max-height: 0;
}
.collapsible-wrapper.collapsed:after
{
  height: 0;
  transition: height 0.3s linear;
  max-height: 50px;
}

/* END of the collapsible implementation; the stuff below
   is just styling for this demo */

#container {
  display: flex;
  align-items: flex-start;
  max-width: 1000px;
  margin: 0 auto;
}


.menu {
  border: 1px solid #ccc;
  box-shadow: 0 1px 3px rgba(0,0,0,0.5);
  margin: 20px;


}

.menu-item {
  display: block;
  background: linear-gradient(to bottom, #fff 0%,#eee 100%);
  margin: 0;
  padding: 1em;
  line-height: 1.3;
}
.collapsible .menu-item {
  border-left: 2px solid #888;
  border-right: 2px solid #888;
  background: linear-gradient(to bottom, #eee 0%,#ddd 100%);
}
.menu-item.toggler {
  background: linear-gradient(to bottom, #aaa 0%,#888 100%);
  color: white;
  cursor: pointer;
}
.menu-item.toggler:before {
  content: '';
  display: block;
  border-left: 8px solid white;
  border-top: 8px solid transparent;
  border-bottom: 8px solid transparent;
  width: 0;
  height: 0;
  float: right;
  transition: transform 0.3s ease-out;
}
.menu-item.toggler.toggled:before {
  transform: rotate(90deg);
}

body { font-family: sans-serif; font-size: 14px; }

*, *:after {
  box-sizing: border-box;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="container">
  <div class="menu">
    <div class="menu-item">Something involving a holodeck</div>
    <div class="menu-item">Send an away team</div>
    <div class="menu-item toggler">Advanced solutions</div>
    <div class="collapsible-wrapper collapsed">
      <div class="collapsible">
        <div class="menu-item">Separate saucer</div>
        <div class="menu-item">Send an away team that includes the captain (despite Riker's protest)</div>
        <div class="menu-item">Ask Worf</div>
        <div class="menu-item">Something involving Wesley, the 19th century, and a holodeck</div>
        <div class="menu-item">Ask Q for help</div>
      </div>
    </div>
    <div class="menu-item">Sweet-talk the alien aggressor</div>
    <div class="menu-item">Re-route power from auxiliary systems</div>
  </div>

  <div class="menu">
    <div class="menu-item">Something involving a holodeck</div>
    <div class="menu-item">Send an away team</div>
    <div class="menu-item toggler">Advanced solutions</div>
    <div class="collapsible-wrapper collapsed">
      <div class="collapsible">
        <div class="menu-item">Separate saucer</div>
        <div class="menu-item">Send an away team that includes the captain (despite Riker's protest)</div>
      </div>
    </div>
    <div class="menu-item">Sweet-talk the alien aggressor</div>
    <div class="menu-item">Re-route power from auxiliary systems</div>
  </div>

  <div class="menu">
    <div class="menu-item">Something involving a holodeck</div>
    <div class="menu-item">Send an away team</div>
    <div class="menu-item toggler">Advanced solutions</div>
    <div class="collapsible-wrapper collapsed">
      <div class="collapsible">
        <div class="menu-item">Separate saucer</div>
        <div class="menu-item">Send an away team that includes the captain (despite Riker's protest)</div>
        <div class="menu-item">Ask Worf</div>
        <div class="menu-item">Something involving Wesley, the 19th century, and a holodeck</div>
        <div class="menu-item">Ask Q for help</div>
        <div class="menu-item">Separate saucer</div>
        <div class="menu-item">Send an away team that includes the captain (despite Riker's protest)</div>
        <div class="menu-item">Ask Worf</div>
        <div class="menu-item">Something involving Wesley, the 19th century, and a holodeck</div>
        <div class="menu-item">Ask Q for help</div>
      </div>
    </div>
    <div class="menu-item">Sweet-talk the alien aggressor</div>
    <div class="menu-item">Re-route power from auxiliary systems</div>
  </div>

</div>

어떻게 작동합니까?

실제로 이런 일을하는 데는 두 가지 변화 가 있습니다 . 그중 하나는 margin-bottom0px (확장 된 상태)에서-2000px 에서 축소 된 상태 ( 이 답변 과 유사)로 전환 합니다. )로 전환됩니다. 여기서 2000은 첫 번째 마법 번호이며, 상자가 이보다 높지 않다는 가정을 기반으로합니다 (2000 픽셀은 합리적인 선택으로 보입니다).

사용하여 margin-bottom전환 자체 만 두 가지 문제가 있습니다.

  • 실제로 2000 픽셀보다 큰 상자가 있다면 margin-bottom: -2000px 모든 것이 숨겨지지 않습니다. 접힌 경우에도 눈에 띄는 물건이 있습니다. 이것은 우리가 나중에 할 사소한 수정입니다.
  • 실제 상자의 높이가 1000 픽셀이고 전환 길이가 300ms 인 경우 가시적 전환은 이미 약 150ms 후에 끝납니다 (또는 반대 방향으로 150ms 늦게 시작됨).

이 두 번째 문제를 해결하는 것은 두 번째 전환이 발생하는 지점이며이 전환은 개념적으로 래퍼의 최소 높이를 대상으로합니다 (실제로는이 min-height속성을 사용하지 않기 때문에 “개념적으로” ).

다음은 동일한 지속 시간의 하단 여백 전환과 최소 높이 전환을 결합하여 지속 시간이 동일한 전체 높이에서 0 높이로 결합 된 전환을 제공하는 방법을 보여주는 애니메이션입니다.

위에서 설명한 애니메이션

왼쪽 막대는 음의 아래쪽 여백이 아래쪽을 위로 밀어 올리는 방법을 보여 주어 보이는 높이를 줄입니다. 가운데 막대는 최소 높이가 축소 사례에서 전환이 조기에 끝나지 않고 확장 사례에서 전환이 늦게 시작되지 않도록하는 방법을 보여줍니다. 오른쪽 막대는 두 가지의 조합으로 상자가 올바른 시간 내에 전체 높이에서 0 높이로 전환되는 방식을 보여줍니다.

내 데모의 경우 최소 최소 높이 값으로 50px로 설정했습니다. 이것은 두 번째 마법 번호이며 상자의 높이보다 낮아야합니다. 50px도 합리적으로 보입니다. 처음에는 높이가 50 픽셀이 아닌 접을 수있는 요소를 만들고 싶을 것 같지 않습니다.

애니메이션에서 볼 수 있듯이 결과 전이는 연속적이지만 구별 할 수는 없습니다. 최소 높이가 아래쪽 여백에 의해 조정 된 전체 높이와 같은 순간에 급격한 속도 변화가 있습니다. 애니메이션에서 두 전환 모두에 선형 타이밍 기능을 사용하고 전체 전환이 매우 느리기 때문에 애니메이션에서 매우 두드러집니다. 실제 경우 (맨 위의 데모)에는 전환이 300ms에 불과하고 하단 여백 전환은 선형이 아닙니다. 나는 두 가지 전환에 대해 다양한 타이밍 기능을 가지고 놀았으며, 결국 다양한 경우에 가장 잘 작동하는 느낌이 들었습니다.

해결해야 할 두 가지 문제가 남아 있습니다.

  1. 축소 된 상태에서 높이가 2000 픽셀 이상인 상자가 완전히 숨겨지지 않는 위의 점
  2. 숨겨지지 않은 경우에는 전환이 실행되지 않는 경우에도 높이가 50 픽셀 미만인 상자가 너무 높은 반대 문제는 최소 높이가 50 픽셀로 유지되기 때문입니다.

컨테이너 요소에 max-height: 0축소 된 경우에 0s 0.3s전환을 통해 첫 번째 문제를 해결합니다 . 이는 실제로 전환이 아니라 max-height지연이 적용됨을 의미합니다. 전환이 완료된 후에 만 ​​적용됩니다. 이것이 올바르게 작동 max-height하려면 반대의 붕괴되지 않은 상태에 대한 숫자도 선택해야합니다 . 그러나 너무 많은 수를 선택하면 전환 품질에 영향을 미치는 2000px의 경우와 달리이 경우에는 실제로 중요하지 않습니다. 우리는 단지 우리가 너무 높은 숫자 선택할 수 있도록 알을 더 높이가이 가까이 올 것입니다. 나는 백만 화소를 골랐다. 백만 픽셀 이상의 높이의 콘텐츠를 지원해야한다고 생각되면 1) 죄송합니다 .2) 단지 몇 개의 0을 추가하십시오.

두 번째 문제는 실제로 min-height최소 높이 전환에 사용하지 않는 이유 입니다. 대신 ::after컨테이너에 의사 요소가 있으며 height50px에서 0으로 전환됩니다. 이는 min-height의사 요소가 현재 가지고있는 높이보다 컨테이너가 줄어들지 않도록합니다. 그러나 height, not을 사용 하고 있기 때문에 min-height이제 max-height트랜지션이 끝나면 의사 요소의 실제 높이를 0으로 설정하여 적어도 한 번의 트랜지션 외부에서도 정확한 높이. 때문에 min-height이다 강한 것보다 max-height우리가 사용 된 경우,이 컨테이너의 작동하지 않을 min-height대신 의사 요소의의height . 그냥max-height이전 단락 max-height에서 전환의 반대쪽 끝에도 값 이 필요합니다. 그러나이 경우에는 50px를 선택할 수 있습니다.

Chrome (Win, Mac, Android, iOS), Firefox (Win, Mac, Android), Edge, IE11 (디버깅을 방해하지 않는 데모의 flexbox 레이아웃 문제 제외) 및 Safari (Mac, iOS)에서 테스트되었습니다. ). flexbox에 관해서는 flexbox를 사용하지 않고도이 작업을 수행 할 수 있어야합니다. 사실 나는 CSS 전환이 없다는 것을 제외하고는 IE7에서 거의 모든 것을 작동시킬 수 있다고 생각합니다.


답변

당신은 약간의 시맨틱 한 무시 무시한 소문으로 할 수 있습니다. 내 일반적인 접근 방식은 콘텐츠 높이를 측정하는 데에만 사용되는 스타일이없는 DIV 인 단일 자식이있는 외부 DIV의 높이를 애니메이션하는 것입니다.

function growDiv() {
  var growDiv = document.getElementById('grow');
  if (growDiv.clientHeight) {
    growDiv.style.height = 0;
  } else {
    var wrapper = document.querySelector('.measuringWrapper');
    growDiv.style.height = wrapper.clientHeight + "px";
  }
}
#grow {
  -moz-transition: height .5s;
  -ms-transition: height .5s;
  -o-transition: height .5s;
  -webkit-transition: height .5s;
  transition: height .5s;
  height: 0;
  overflow: hidden;
  outline: 1px solid red;
}
<input type="button" onclick="growDiv()" value="grow">
<div id='grow'>
  <div class='measuringWrapper'>
    <div>
      The contents of my div.
    </div>
    <div>
      The contents of my div.
    </div>
    <div>
      The contents of my div.
    </div>
    <div>
      The contents of my div.
    </div>
    <div>
      The contents of my div.
    </div>
    <div>
      The contents of my div.
    </div>
  </div>
</div>

단지에 분배 할 수 있도록 하나 싶습니다 .measuringWrapper그냥 자동으로 DIV의 높이를 설정하고 애니메이션을 가지고 있지만 그 (높이가 세트를 얻을 수 있지만 애니메이션이 발생하지 않는다) 작동하지 않습니다.

function growDiv() {
  var growDiv = document.getElementById('grow');
  if (growDiv.clientHeight) {
    growDiv.style.height = 0;
  } else {
    growDiv.style.height = 'auto';
  }
}
#grow {
  -moz-transition: height .5s;
  -ms-transition: height .5s;
  -o-transition: height .5s;
  -webkit-transition: height .5s;
  transition: height .5s;
  height: 0;
  overflow: hidden;
  outline: 1px solid red;
}
<input type="button" onclick="growDiv()" value="grow">
<div id='grow'>
  <div>
    The contents of my div.
  </div>
  <div>
    The contents of my div.
  </div>
  <div>
    The contents of my div.
  </div>
  <div>
    The contents of my div.
  </div>
  <div>
    The contents of my div.
  </div>
  <div>
    The contents of my div.
  </div>
</div>

내 해석은 애니메이션을 실행하려면 명시적인 높이가 필요하다는 것입니다. 높이 (시작 또는 끝 높이)가이면 높이에서 애니메이션을 얻을 수 없습니다 auto.


답변

CSS3 전환을 사용하여 높이에 애니메이션을 적용하는 시각적 해결 방법은 패딩을 애니메이션으로 만드는 것입니다.

완전히 지우기 효과는 얻지 못하지만 전환 지속 시간 및 패딩 값을 사용하면 충분히 가까워 질 수 있습니다. 높이 / 최대 높이를 명시 적으로 설정하지 않으려는 경우 이것이 원하는 것이어야합니다.

div {
    height: 0;
    overflow: hidden;
    padding: 0 18px;
    -webkit-transition: all .5s ease;
       -moz-transition: all .5s ease;
            transition: all .5s ease;
}
div.animated {
    height: auto;
    padding: 24px 18px;
}

http://jsfiddle.net/catharsis/n5XfG/17/ (stephband의 jsFiddle 이상에서 작동)