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


2134

나는 노력하고 있습니다 <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>


height:auto/max-height영역을 확장 height하려는 경우 제한하려는 것보다 큰 경우에만 솔루션이 작동 한다고 생각합니다 . 당신이있는 경우 max-height의를 300px하지만, 반환 할 수있는 콤보 상자 드롭 다운은, 50px다음, max-height도움이되지 않습니다, 50px(가) 때문에 요소의 수에 따라 변수입니다, 당신은 내가 그것을 해결할 수없는 불가능한 상황에 도달 할 수 height없는 고정 height:auto솔루션 이었지만 이것으로 전환을 사용할 수 없습니다.
Christopher Thomas

51
OP는 js가 아닌 CSS 솔루션을 시도하고 있습니다. 그렇지 않으면 오버플로와 애니메이션을 사용할 수 있습니다.
Toni Leigh

5
@VIDesignz : 그러나 내부 div의 -100 % margin-top 은 높이가 아닌 래퍼 div 의 너비 를 받습니다 . 따라서이 솔루션에는 최대 높이 솔루션과 같은 종류의 문제가 있습니다. 또한 너비가 컨텐츠 높이보다 작은 경우 모든 컨텐츠가 -100 % margin-top로 숨겨지는 것은 아닙니다. 따라서 이것은 잘못된 해결책입니다.
GregTom

1
적절한 솔루션의 사양 및 구현에 대한 자세한 내용은 github.com/w3c/csswg-drafts/issues/626 을 참조하십시오
Ben Creasy

답변:


2745

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>


323
이것은 잘 작동합니다! 그것은 처음에 매우 high..hmm는 최고 높이 시작될 있기 때문에, 시작할 때 지연이 제외하고, 나는이 다소 성가신 생각
VSYNC

175
+1 훌륭한 솔루션! 전이 속도는 최대 높이 값으로 전이하도록 지정한 시간으로 계산되지만 높이가 최대 높이보다 작기 때문에 실제 높이로의 전이는 지정된 시간.
kingjeffrey

50
실제 계산 된 값보다 훨씬 큰 값을 사용해야하는 경우 이로 인해 추악한 전환 종료가 발생할 수 있습니다. 화면 크기가 다르기 때문에 div가 0 높이에서 콘텐츠 높이로 크게 증가하는 동안 이것을 알았습니다 (2560x1440 모니터의 2 줄 대 스마트 폰의 10 줄 이상). 이를 위해 나는 js로 갔다.
jpeltoniemi 10

44
한 방향으로는 지연이 발생하지만 다른 방향으로는 지연되지 않으므로 매우 못생긴 솔루션입니다.
Tim

84
이것은 꽤 게으른 해결책입니다. 컨테이너의 확장 된 높이가 다소 예측할 수 없기 때문에 OP가 height : auto를 사용하려고한다고 가정합니다. 이 솔루션은 애니메이션이 표시되기 전에 지연을 유발합니다. 또한 애니메이션의 보이는 지속 시간은 예측할 수 없습니다. 각 컨테이너 자식 노드의 결합 된 높이를 계산 한 다음 정확한 높이 값으로 완화하면 훨씬 더 예측 가능하고 매끄러운 결과를 얻을 수 있습니다.
Shawn Whinnery

314

대신 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를 사용하도록 변경했습니다 .


6
이 CSS3 전이 가능한 브라우저에서 잘 작동하지 않습니다 때문에 나는이 대답을 upvoting 해요,하지만이 있음을 주목해야한다 IE <9 전혀 작동하지 않습니다 , 그리고 <IE에 (그냥 이동합니다) 애니메이션 실 거예요 (10)
Hailwood

215
이 방법은 원하는 효과를 부분적으로 만 달성하지만 실제로 공간을 제거 하지는 않습니다 . 변형 된 상자는 상대적으로 배치 된 요소처럼 작동합니다. 공간의 크기에 관계없이 공간이 사용됩니다. 이 jsFiddle 을 확인 하십시오. 첫 번째 것을 가져 와서 하단에 가짜 텍스트를 추가하십시오. 상자 높이가 0으로 조정될 때 아래 텍스트가 어떻게 움직이지 않는지 참고하십시오.
animuson

9
지금은 수행합니다 jsfiddle.net/gNDX3/1은 기본적으로 당신은 당신이 필요에 따라 요소의 스타일을해야합니다. CSS / HTML에는 동작과 같은 은색 글 머리 기호 나 위젯이 없습니다.
dotnetCarpenter

70
다른 접근법을 시도하는 누군가에게 박수를 보내지 만,이 솔루션이 가져 오는 실제 효과와 합병증은 이미 끔찍한 최대 높이 핵보다 훨씬 나쁩니다. 사용하지 마십시오.
mystrdat

2
@SquareCat 괜찮아. : 여기처럼 더 서랍을 하나입니다 jsfiddle.net/dotnetCarpenter/WTL2r
dotnetCarpenter

202

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


12
일반적으로 문제를 해결하는 방법은 여러 가지가 있으며 모두 적절하거나 가능한 것은 아닙니다. @JedidiahHurt와 Ryan Ore가 Q & A 사이트에서 가능한 답변을 제한하려는 이유를 모르겠습니다. 특히이 답변을 고려한 것이 여기에 처음이었습니다. 수락 된 답변이 해결 방법이므로 두 배로 그렇습니다.
Hooray Im 님이

5
@jake의 대답은 우아하지도 않고 정확하지도 않습니다. 여기에 연결된 답변이 훨씬 좋습니다. 올바르게 작동하고 모든 규모의 사례를 처리합니다. 수용 된 답변에 대해 말할 수는 없습니다.
GraphicsMuncher

5
예 : this.$element[dimension](this.$element[dimension]())[0].offsetHeight
Andy

4
이것은 어떻게 든 수정 될 예정입니까? 내 말은, 이것은 0 높이에서 auto... 로 전환 할 수있을 것으로 기대되는 것은 자연스러운
Augustin Riedinger

6
@Meliodas "아니오 / 아니요"는 스택 오버플로에 대한 질문에 대한 유효하고 수용 가능한 답변입니다.
TylerH

122

내가 항상 사용했던 것을이 솔루션은 다음 축소, 첫 번째 페이드 아웃이었다 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>


나를 위해 깔끔하게 일했습니다. jQuery slideUp / Down과는 다릅니다. 오래된 컴퓨터 또는 모바일과 같이 약한 CPU와 동시에 많은 CPU를 열고 닫는 경우에만 차이점을 볼 수 있습니다.
크루즈 누네즈

3
버튼이나 텍스트가 아닌 다른 요소가 있으면 가리 키지 않고 원치 않는 공백이 생깁니다.
Dennis W

3
모든 하위 요소를 선택하고 *다른 변경 사항을 적용 하여 더 세밀하게 조정할 수 있습니다 . 그러나 버튼의 스타일이 올바르게 설정되어 있으면 위의 코드에 의해 버튼이 영향을 받았을 것입니다 em.
Steven Vachon

1
내 경우, 나는 또한 추가 할 필요 line-height: 0;border-width: 0;
안드레이 샤틸 로프

1
developer.mozilla.org/en-US/docs/Web/CSS/…line-height 값을 올바르게 피하지 않으면 조정할 필요가 없습니다 .
Steven Vachon

93

나는 이것이이 질문에 대한 서른 뭔가라는 것을 알고 있지만 그만한 가치가 있다고 생각합니다. 이것은 다음과 같은 속성을 가진 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에서 거의 모든 것을 작동시킬 수 있다고 생각합니다.


35
적어도 솔루션이나 코드 예제를 단축 (단순화) 할 수 있기를 바랍니다. 코드 예제의 90 %가 답변과 관련이없는 것처럼 보입니다.
길 Epshtain

collapsible-wrapper위치가 절대적 인 경우 이러한 전환을 작동시키는 방법이 있습니까? overflow: hidden상위에 절대적 위치 요소 전이를 방해하지만 필요하다.
pmkro

1
@ pmkro 그래, 나도 그 문제가 있었다. 후자와 달리 전자를 전환 할 수 있기 때문에 clip-path: polygon(...)대신 대신을 사용하여 해결했습니다 overflow: hidden. 구형 브라우저의 대체품으로 추가 스케일링 변환을 사용했습니다. github.com/StackExchange/Stacks/blob/develop/lib/css/components/…
balpha

2
좋은. 이것은 정말 잘 작동합니다. 허용되는 답변이어야 함
Henry Ing-Simmons

83

당신은 약간의 시맨틱 한 무시 무시한 소문으로 할 수 있습니다. 내 일반적인 접근 방식은 콘텐츠 높이를 측정하는 데에만 사용되는 스타일이없는 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.


10
이것은 자바 스크립트에 의존하기 때문에 자바 스크립트를 사용하여 measurementWrapper를 쉽게 추가 할 수도 있습니다!
Quickredfox

18
랩퍼없이 할 수 있습니다. 그냥 : function growDiv () {var growDiv = document.getElementById ( 'grow'); if (growDiv.clientHeight) {growDiv.style.height = 0; } else {growDiv.style.height = growDiv.scrollHeight + 'px'; }}
user1742529 2016 년

8
이것을 확인하십시오 ... 간단한 답변 jsfiddle.net/n5XfG/2596 에 대한 이야기 ... 당신의 대답은 아무런 이유없이 미친 듯이 복잡합니다. 필요 없음 max-height, 필요없이 auto, 자바 스크립트 특히 필요가 없습니다! 두 가지 간단한 선언
VIDesignz

12
@VIDesignz 마진이 100 % 이상입니다. 높이가 아닌 요소 너비 의 100 %입니다 . 즉, 너비보다 높이가 큰 요소는 숨겨지지 않습니다. 또한 실제 애니메이션 속도는 정의 된 속도와 완전히 다릅니다.
Timo Türschmann

3
Timo의 의견에 대해 자세히 읽을 때까지 VIDesignz의 답변에 대해 흥분했습니다. 그렇습니다 margin-top(그리고 margin-bottom)는 백분율로 정의 될 때 너비 와 관련이 있습니다. 그렇습니다. 어리석은 일이지만 열기 및 닫기 애니메이션 타이밍이 완전히 다른 이유도 설명합니다. 코딩 된 최대 높이. 이것이 왜 그렇게하기 어려운가?
Coderer

52

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 이상에서 작동)


3
이것이 가장 좋은 대답이라고 생각합니다. 이 기술은 어린이의 패딩 조정으로 확장 될 수 있습니다. 내 경우에는 공개 할 내용 중 일부에서 명시 적 높이 전환과 결합 할 수 있었고 총 효과는 최대 높이 해결 방법보다 훨씬 성공적이며 공개에는 적합하지만 어색한 순간을 초래합니다. 숨기기 지연. 내 앱이 응답하지 않는 것처럼 보이는 의미없는 지연을 도입하는 것보다 더 빨리 애니메이션하지는 않을 것입니다. 나는 많은 사람들이 그것이 받아 들여질 것이라고 생각하는 것에 놀랐습니다.
세미콜론

17
여기를 제외하고는 높이를 전혀 애니메이션하지 않습니다. 패딩에 애니메이션을 적용하는 중입니다. 현재 상태에서 0까지 애니메이션을 적용 할 수 있기 때문에 잘 사라질 수 있지만, 확장 될 때 자세히 보면 텍스트와 함께 열린 상태로 팝업되고 패딩 만 애니메이션으로 표시됩니다. 0에서 자동으로 애니메이션하는 방법을 모르는 경우 숫자 범위가 필요합니다. 트위닝이 작동하는 방식입니다.
Rob R

이것은 해킹되지 않은 좋은 해결 방법입니다. 질문에 대한 최선의 답변 은 아니지만 저에게 도움이되는 대안입니다. 가끔은 그냥 약간의 높이 애니메이션이 아닌 전체 애니메이션 :)의 효과가 필요
이반 더스트

이 솔루션은 전환 지연을 사용할 때도 실패합니다.
Michel Joanisse

또한이 솔루션이 애니메이션이 충분히 빠르면 유동적 인 전환을 제공하는 깨끗한 해결 방법이라는 데 동의합니다 (제 경우에는 전환이 0.1s 인 아코디언에는 완벽합니다!). 그것은 많은 응용 프로그램을 스위트하지는 않지만 다른 사람 이이 질문에 답하지 않습니다!
Remi D

46

내 해결 방법은 멋진 부드러운 애니메이션을 위해 최대 높이를 정확한 내용 높이로 전환 한 다음 transitionEnd 콜백을 사용하여 최대 높이를 9999px로 설정하여 내용의 크기를 자유롭게 조정할 수 있습니다.

var content = $('#content');
content.inner = $('#content .inner'); // inner div needed to get size of content when closed

// css transition callback
content.on('transitionEnd webkitTransitionEnd transitionend oTransitionEnd msTransitionEnd', function(e){
    if(content.hasClass('open')){
        content.css('max-height', 9999); // try setting this to 'none'... I dare you!
    }
});

$('#toggle').on('click', function(e){
    content.toggleClass('open closed');
    content.contentHeight = content.outerHeight();
    
    if(content.hasClass('closed')){
        
        // disable transitions & set max-height to content height
        content.removeClass('transitions').css('max-height', content.contentHeight);
        setTimeout(function(){
            
            // enable & start transition
            content.addClass('transitions').css({
                'max-height': 0,
                'opacity': 0
            });
            
        }, 10); // 10ms timeout is the secret ingredient for disabling/enabling transitions
        // chrome only needs 1ms but FF needs ~10ms or it chokes on the first animation for some reason
        
    }else if(content.hasClass('open')){  
        
        content.contentHeight += content.inner.outerHeight(); // if closed, add inner height to content height
        content.css({
            'max-height': content.contentHeight,
            'opacity': 1
        });
        
    }
});
.transitions {
    transition: all 0.5s ease-in-out;
    -webkit-transition: all 0.5s ease-in-out;
    -moz-transition: all 0.5s ease-in-out;
}

body {
    font-family:Arial;
    line-height: 3ex;
}
code {
    display: inline-block;
    background: #fafafa;
    padding: 0 1ex;
}
#toggle {
    display:block;
    padding:10px;
    margin:10px auto;
    text-align:center;
    width:30ex;
}
#content {
    overflow:hidden;
    margin:10px;
    border:1px solid #666;
    background:#efefef;
    opacity:1;
}
#content .inner {
    padding:10px;
    overflow:auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<div id="content" class="open">
    <div class="inner">
        <h3>Smooth CSS Transitions Between <code>height: 0</code> and <code>height: auto</code></h3>
        <p>A clever workaround is to use <code>max-height</code> instead of <code>height</code>, and set it to something bigger than your content. Problem is the browser uses this value to calculate transition duration. So if you set it to <code>max-height: 1000px</code> but the content is only 100px high, the animation will be 10x too fast.</p>
        <p>Another option is to measure the content height with JS and transition to that fixed value, but then you have to keep track of the content and manually resize it if it changes.</p>
        <p>This solution is a hybrid of the two - transition to the measured content height, then set it to <code>max-height: 9999px</code> after the transition for fluid content sizing.</p>
    </div>
</div>

<br />

<button id="toggle">Challenge Accepted!</button>


14
@ Derija93 평범한 오래된 자바 스크립트 시간 초과 애니메이션을 사용하고 있습니다. 대신 CSS3 전환을 사용해야합니다.
Adam

3
그래 그러나 예를 들어 라이브러리에서 이미 jQuery를 사용하여 "쓰기 적음, 더 많이"더 많은 코드를 제공하는 경우 "CSS3 전환"을 사용하는 이유는 무엇입니까? jQuery를 사용하지 않아서 거의 모든 웹 사이트에서 실행될 수 있다면 버전이 훨씬 복잡하지만 더 좋아 보일 수 있음을 지적하고 싶습니다. 나는 그것이 크게 잘못했다고 생각합니다. 죄송합니다. ;)
Kiruse

27
@ Derija93 아마도 CSS3 전환이 (내가 찾을 수있는 모든 소스에 따라) jQuery 애니메이션보다 훨씬 나은 성능을 가지고 있기 때문일 것입니다. (사실 여기에 나를 데리고 내 현재 사용 사례를 위해 대단히 중요.)
마크 Amery

4
@ Derija93 'Cause Javascript 애니메이션은 CSS3 전환과 비교할 때 느리게 실행되며 jQuery 애니메이션에서는 애니메이션 루프에 대해 걱정해야합니다. 클릭시 무언가에 애니메이션을 적용한 다음 빠르게 클릭하여 애니메이션이 반복되는 것을보십시오. 이것은 CSS3로 처리됩니다.
AlbertEngelB

2
@ Dropped.on.Caprica 이것은 조금 오래된 것입니다. 나는 이미 그가 보여 주려고하는 개념을 잘못 이해했다고 말했다. 어쨌든 간단한 애니메이션의 .stop경우 다소 복잡한 애니메이션 루프 문제에 대한 트릭을 수행합니다. 이제 높이와 색상에 애니메이션을 적용하지만 높이 애니메이션 만 중단하고 싶을 때는 조금 까다로워집니다.
Kiruse

43

허용되는 답변은 대부분의 경우 효과가 있지만 div높이가 크게 다를 수있는 경우 제대로 작동하지 않습니다 . 애니메이션 속도는 콘텐츠의 실제 높이에 의존하지 않으며 고르지 않게 보일 수 있습니다.

CSS를 사용하여 실제 애니메이션을 계속 수행 할 수 있지만을 사용하는 대신 JavaScript를 사용하여 항목의 높이를 계산해야합니다 auto. 호환성을 원한다면 (최신 버전의 Chrome에서 작동 :) jQuery가 필요하지 않지만 조금 수정해야 할 수도 있습니다.

window.toggleExpand = function(element) {
    if (!element.style.height || element.style.height == '0px') { 
        element.style.height = Array.prototype.reduce.call(element.childNodes, function(p, c) {return p + (c.offsetHeight || 0);}, 0) + 'px';
    } else {
        element.style.height = '0px';
    }
}
#menu #list {
    height: 0px;
    transition: height 0.3s ease;
    background: #d5d5d5;
    overflow: hidden;
}
<div id="menu">
    <input value="Toggle list" type="button" onclick="toggleExpand(document.getElementById('list'));">
    <ul id="list">
        <!-- Works well with dynamically-sized content. -->
        <li>item</li>
        <li><div style="height: 100px; width: 100px; background: red;"></div></li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
    </ul>
</div>


이것은 도움이 될 수 있지만 더 나은 예없이 그것을 사용하는 방법을 모르기 때문에 말할 수 없습니다.
Ivan Durst

1
DOM 요소 (예 : from document.getElementById('mydiv')또는 $('#mydiv').get())를 전달하면 함수가 숨기거나 표시하는 것 사이를 전환합니다. CSS 전환을 설정하면 요소가 자동으로 애니메이션됩니다.
Oleg Vaskevich가

스 니펫을 추가했습니다. 동적 크기의 컨텐츠에 적합합니다.
Oleg Vaskevich가

3
-1, "CSS 사용"이 아니기 때문에. 문제의 핵심은 JS 프리 솔루션입니다. 나는 해킹 아니다은 "올바른"대답이,이,하지만 ...있을 거라고 생각
dudewad

16
JS를 사용하는 공감대-진심으로? 여기에 절반의 답변은 JS를 사용하므로 downvote가 공평하거나 필요하지 않은 것 같습니다. 또한이 답변은 여전히 ​​CSS를 사용하여 실제 애니메이션을 수행하고 있으며 IMO는 OP의 핵심이었습니다. JS가 사용되는 유일한 것은 실제 CSS 를 계산하는 것이 불가능 하기 때문에 실제 높이를 계산하는 것입니다 ( min-height예상 답변에서 설정 하면 목록의 크기가 크게 다를 때 애니메이션 속도에 문제가 발생합니다).
Oleg Vaskevich

30

Element.scrollHeight여기서 유용 할 수 있고 순수한 CSS 전환과 함께 사용될 수있는 속성에 대한 언급은 거의 없습니다 . 속성은 높이가 축소 된 결과 (예 :)로 인해 내용이 오버플로되는지 여부와 관계없이 항상 요소의 "전체"높이를 포함합니다 height: 0.

이와 같이, height: 0(효과적으로 완전히 붕괴 된) 요소의 경우, "정상"또는 "전체"높이는 그 scrollHeight값 (불변의 픽셀 길이)을 통해 여전히 쉽게 이용 가능하다 .

이러한 요소의 경우 이미 예를 들어 ( ul원래 질문에 따라 사용) 과 같이 전환이 설정되어 있다고 가정합니다 .

ul {
    height: 0;
    transition: height 1s; /* An example transition. */
}

CSS 만 사용하여 원하는 애니메이션 "확장"높이를 다음과 같이 트리거 할 수 있습니다 (여기서 ul변수가 목록을 가정한다고 가정 ).

ul.style.height = ul.scrollHeight + "px";

그게 다야. 목록을 축소해야하는 경우 다음 두 문 중 하나가 수행됩니다.

ul.style.height = "0";
ul.style.removeProperty("height");

내 특정 유스 케이스는 알려지지 않았고 종종 상당한 길이의 애니메이션 목록을 중심으로 진행되었으므로 임의의 "충분히 큰" height또는 max-height사양으로 설정하고 갑자기 스크롤해야하는 컷오프 컨텐츠 또는 컨텐츠를 위험에 빠뜨리는 것이 불편했습니다 ( overflow: auto예 : . 또한, 완화 및 타이밍과 깨진 max-height사용 된 높이가 훨씬 빨리이 걸릴 것보다 최대 값에 도달 할 수 있기 때문에, 기반 솔루션을 max-height손에 9999px. 그리고 화면 해상도가 커짐에 따라 픽셀 길이는 9999px입에 나쁜 맛을 남깁니다. 이 특정 솔루션은 내 의견으로는 문제를 우아한 방식으로 해결합니다.

마지막으로, CSS 주소 작성자의 향후 개정판에서 이러한 종류의 작업을 훨씬 더 우아하게 수행해야합니다. "계산 된"대 "사용 된"및 "해결 된"값의 개념을 다시 검토하고 전환이 계산에 적용되어야하는지 고려하십시오. width및 와의 전환을 포함한 값 height(현재 약간의 특수 처리가 수행됨).


6
Element.scrollHeight속성을 사용하여 DOM과 상호 작용 하려면 JavaScript가 필요하고 질문에서 분명히 알 수 있듯이 JavaScript 없이이 작업을 수행하기 원하기 때문에 다른 답변에서 찾지 못했습니다 .
TylerH

3
1 페이지의 가장 높은 답변이 표시되는 것처럼이 문제를 해결할 수있는 두 개의 의사 클래스 외에도 CSS의 다른 부분이 많이 있습니다. JavaScript에서 스타일을 설정하는 것은 "순수한 CSS"가 아닙니다. 왜냐하면 JS를 먼저 설정해야하기 때문입니다. CSS 전용 솔루션을 요청하는 사람은 종종 JavaScript를 삽입 할 수 없거나 현재 프로젝트 또는 역할에 의해 허용되지 않기 때문입니다.
TylerH

29

max-height각 상태마다 다른 전환 완화 및 지연과 함께 사용하십시오 .

HTML :

<a href="#" id="trigger">Hover</a>
<ul id="toggled">
    <li>One</li>
    <li>Two</li>
    <li>Three</li>
<ul>

CSS :

#toggled{
    max-height: 0px;
    transition: max-height .8s cubic-bezier(0, 1, 0, 1) -.1s;
}

#trigger:hover + #toggled{
    max-height: 9999px;
    transition-timing-function: cubic-bezier(0.5, 0, 1, 0); 
    transition-delay: 0s;
}

예를 참조하십시오 : http://jsfiddle.net/0hnjehjc/1/


12
여기서 문제는 동적 환경에서 충분한 공간을 확보하기 위해 우스운 최대 높이를 사용해야한다는 것 999999px입니다. 반면에이 값에서 프레임이 계산되므로 애니메이션이 이동합니다. (타이밍 기능 CORR) 당신은 애니메이션을 한 방향으로 "지연"다른 방향으로 정말 빨리 끝으로 끝낼 수 있습니다 그래서
줄리안 F. Weinert을

29

하드 코딩 된 값이 없습니다.

자바 스크립트가 없습니다.

근사치가 없습니다.

속임수는 숨겨져 있고 복제 된 것입니다. div 브라우저가 100 %의 의미를 이해하도록하기 위해 것입니다.

이 방법은 애니메이션하려는 요소의 DOM을 복제 할 수있을 때마다 적합합니다.

.outer {
  border: dashed red 1px;
  position: relative;
}

.dummy {
  visibility: hidden;
}

.real {
  position: absolute;
  background: yellow;
  height: 0;
  transition: height 0.5s;
  overflow: hidden;
}

.outer:hover>.real {
  height: 100%;
}
Hover over the box below:
<div class="outer">
  <!-- The actual element that you'd like to animate -->
  <div class="real">
unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable
content unpredictable content unpredictable content unpredictable content
  </div>
  <!-- An exact copy of the element you'd like to animate. -->
  <div class="dummy" aria-hidden="true">
unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable
content unpredictable content unpredictable content unpredictable content
  </div>
</div>


훌륭하게 완료되었습니다-이것은 실제로 존재해서는 안되는 문제에 대한 유효한 솔루션입니다. 전환이 "선형"으로 설정되어 있지 않으면 최대 높이 애니메이션에 기본이 적용됩니다. 높이가 가변적 인 CMS 콘텐츠에 애니메이션을 적용하는 것도 (분명히) 매우 나쁩니다.
M_Willett

이것은 영리하지만 DOM 요소와 내용을 복제하는 것은 편안하지 않습니다.
Andre Figueiredo

transform: scaleY(1)이 전환이 공간을 제거하지 않기 때문에 컨테이너와 더 많은 성능없이 애니메이션을 적용하여이 작업을 수행 할 수 있습니다 .
Fabian von Ellerts

21

이 게시물을 게시 할 때 이미 30 개가 넘는 답변이 있지만 제이크 가 이미 받아 들인 답변 에 대한 답변이 향상되었다고 생각 합니다.

max-height많은 주석 작성자가 언급했듯이 max-height값을 실제 높이에 매우 가깝게 설정해야 하거나 지연 이 발생하기 때문에 CSS3 전환을 사용하여 발생하는 문제에 만족하지 않았습니다 . 이 JSFiddle 참조해당 문제의 예는 을 .

이 문제를 해결하기 위해 (아직 JavaScript를 사용하지 않는 동안) transform: translateYCSS 값 을 전환하는 다른 HTML 요소를 추가했습니다 .

모두이 방법 max-heighttranslateY사용은 : max-height반면, 그 아래 요소를 아래로 밀어 요소를 수 있도록 translateY우리가 원하는 "즉시"효과를 제공합니다. 문제는 max-height여전히 존재하지만 그 효과는 줄어 듭니다. 이것은 당신이 당신의 max-height가치를 위해 더 큰 높이를 설정하고 덜 걱정할 수 있음을 의미합니다 .

전반적인 이점은 다시 전환 (축소) 할 때 사용자가 translateY애니메이션을 즉시 볼 수 있으므로 max-height소요 시간이 실제로 중요하지 않다는 것 입니다.

바이올린으로 솔루션

body {
  font-family: sans-serif;
}

.toggle {
  position: relative;
  border: 2px solid #333;
  border-radius: 3px;
  margin: 5px;
  width: 200px;
}

.toggle-header {
  margin: 0;
  padding: 10px;
  background-color: #333;
  color: white;
  text-align: center;
  cursor: pointer;
}

.toggle-height {
  background-color: tomato;
  overflow: hidden;
  transition: max-height .6s ease;
  max-height: 0;
}

.toggle:hover .toggle-height {
  max-height: 1000px;
}

.toggle-transform {
  padding: 5px;
  color: white;
  transition: transform .4s ease;
  transform: translateY(-100%);
}

.toggle:hover .toggle-transform {
  transform: translateY(0);
}
<div class="toggle">
  <div class="toggle-header">
    Toggle!
  </div>
  <div class="toggle-height">
    <div class="toggle-transform">
      <p>Content!</p>
      <p>Content!</p>
      <p>Content!</p>
      <p>Content!</p>
    </div>
  </div>
</div>

<div class="toggle">
  <div class="toggle-header">
    Toggle!
  </div>
  <div class="toggle-height">
    <div class="toggle-transform">
      <p>Content!</p>
      <p>Content!</p>
      <p>Content!</p>
      <p>Content!</p>
    </div>
  </div>
</div>


@davidtaubmann의 멋진 비교, 펜의 차이점을 잘 보여줍니다! 나는 그 압축 효과를주는 방식 이 마음에 들지 않아서 translateY끝났 습니다. scalescale
Andrew Messier

@ andrew-messier에게 감사드립니다. 실수가 있기 때문에 주석을 삭제했습니다. translateY는 codepen.io/davidtaubmann/pen/zKZvGP에서 실례 가 아닙니다 (이동 할 자녀가 없기 때문에 수정이 필요합니다) ... 하나만 MAX-HEIGHT와 비교하고 완벽하게 볼 수 있습니다 ( codeanswer.io/davidtaubmann/pen/jrdPER) . 이 모든 것이 제가 사용하고있는 목표 방법론에 많은 도움이되었습니다
DavidTaubmann

18

좋아, 그래서 나는 간단한 대답을 생각해 냈다 ... 아니 max-height, relative위치 지정, li요소 에 대한 작업 및 순수한 CSS입니다. CSS로 판단하더라도 Firefox 이외의 다른 테스트는하지 않았지만 모든 브라우저에서 작동합니다.

피들 : http://jsfiddle.net/n5XfG/2596/

CSS

.wrap { overflow:hidden; }

.inner {
            margin-top:-100%;
    -webkit-transition:margin-top 500ms;
            transition:margin-top 500ms;
}

.inner.open { margin-top:0px; }

HTML

<div class="wrap">
    <div class="inner">Some Cool Content</div>
</div>

13
이것은 요소의 높이가 너비를 초과 할 때까지 작동합니다. 백분율을 사용하여 여백을 계산하는 방법의 기초입니다. 요소의 너비를 기준으로 계산됩니다. 따라서 1000px 너비의 요소가있는 경우 1100px의 요소가 너무 커서이 솔루션이 작동하지 않으므로 해당 음의 상단 여백을 늘려야합니다. 기본적으로 높이 또는 최대 높이를 사용하는 것과 동일한 문제입니다.
dudewad

15

편집 : 업데이트 된 답변을 아래로 스크롤
하여 드롭 다운 목록을 만들고이 게시물을 보았습니다 ... 많은 답변이 있지만 드롭 다운 목록도 공유하기로 결정했습니다 ... 완벽하지는 않지만 적어도 CSS 만 사용합니다. 쓰러지 다! 나는 변환을 사용했습니다 : translate Y를 (Y)를보기로 목록을 변환하는 ...
당신은 더 테스트에서 볼 수
http://jsfiddle.net/BVEpc/4/
모든 리튬 뒤에 내가 배치 한 사업부 내를하기 때문에 드롭 다운 목록이 올라 와서 올바르게 표시하려면 내 div 코드는 다음과 같습니다.

#menu div {
    transition: 0.5s 1s;
    z-index:-1;
    -webkit-transform:translateY(-100%);
    -webkit-transform-origin: top;
}

호버는 :

#menu > li:hover div {
    transition: 0.5s;
    -webkit-transform:translateY(0);
}

ul 높이가 콘텐츠로 설정되어 있기 때문에 본문 콘텐츠를 가져올 수 있으므로 ul에 대해이 작업을 수행했습니다.

 #menu ul {
    transition: 0s 1.5s;
    visibility:hidden;
    overflow:hidden;
}

호버 :

#menu > li:hover ul {
     transition:none;
     visibility:visible;
}

전환 후 두 번째는 지연이며 내 드롭 다운 목록이 애니메이션으로 닫히면 숨겨집니다 ...
나중에 누군가 가이 혜택을 누리기를 바랍니다.

편집 : 나는 실제로이 프로토 타입을 사용하는 ppl을 믿을 수 없습니다! 이 드롭 다운 메뉴는 하나의 하위 메뉴에만 해당되며 그게 전부입니다 !! IE 8 지원으로 ltr 및 rtl 방향에 대한 두 개의 하위 메뉴를 가질 수있는 더 나은 메뉴를 업데이트했습니다.
LTR을위한
바이올린 RTL을 위한 바이올린
누군가가 앞으로이 기능을 유용하게 사용할 수 있기를 바랍니다.


11

최소 높이와 최대 높이를 제공하여 높이 : 0에서 높이 : 자동으로 전환 할 수 있습니다.

div.stretchy{
    transition: 1s linear;
}

div.stretchy.hidden{
    height: 0;
}

div.stretchy.visible{
    height: auto;
    min-height:40px;
    max-height:400px;
}

@Stuart Badminton 실무 예제를 제공 할 수 있습니까? :( 나는이 함께 넣어 가지고 있지만 작업 어디하지 않는 것 jsfiddle.net/gryzzly/n5XfG
미샤 Reyzlin

5
문제는 전환 규칙에 있습니다. 작동하려면 최소 및 최대 높이로 전환을 적용해야합니다. 전이 : 높이 .5s 선형, 분 높이 .5s 선형, 최대 높이를 .5s 선형
스튜어트 배드민턴

2
: 여기 당신은 애니메이션 최대 높이에 필요한 말했다 것처럼, 내가 나중에있어 무엇 jsfiddle.net/gryzzly/n5XfG/3
미샤 Reyzlin

11
물론 이것에 문제가 있습니다. 최대 높이에 애니메이션을 적용하는 데 걸리는 시간은 상자의 자동 높이로 전환하는 데 걸리는 시간이 아닙니다. 최대 높이에 애니메이션이 적용되기 전에 높이 : 자동에 도달합니다. 마찬가지로 0으로 전환 할 때 최대 높이가 height : auto보다 큰 높이에서 시작하므로 전환이 즉시 시작되지 않습니다. jsfiddle.net/n5XfG/11
stephband

당신은 맞습니다, 추가 테스트에서 나는 이것을 알았습니다. 전체 높이 : 0 ~ 높이 : 자동이 구현되는지 여부를 모르겠지만 일부 상황에서 최대 높이를 사용하면 CSS 만 사용하여 불가능한 상황을 해결할 수 있습니다.
스튜어트 배드민턴

10

Flexbox 솔루션

장점 :

  • 단순한
  • JS 없음
  • 부드러운 전환

단점 :

  • 요소는 고정 높이 플렉스 용기에 넣어야합니다

그것이 작동하는 방식은 항상 flex-basis, 즉 내용이있는 요소에 자동을 적용하고 대신 flex-grow 및 flex-shrink를 전환하는 것입니다.

편집 : Xbox One 인터페이스에서 영감을 얻은 JS Fiddle 개선.

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  transition: 0.25s;
  font-family: monospace;
}

body {
  margin: 10px 0 0 10px;
}

.box {
  width: 150px;
  height: 150px;
  margin: 0 2px 10px 0;
  background: #2d333b;
  border: solid 10px #20262e;
  overflow: hidden;
  display: inline-flex;
  flex-direction: column;
}

.space {
  flex-basis: 100%;
  flex-grow: 1;
  flex-shrink: 0;    
}

p {
  flex-basis: auto;
  flex-grow: 0;
  flex-shrink: 1;
  background: #20262e;
  padding: 10px;
  width: 100%;
  text-align: left;
  color: white;
}

.box:hover .space {
  flex-grow: 0;
  flex-shrink: 1;
}
  
.box:hover p {
  flex-grow: 1;
  flex-shrink: 0;    
}
<div class="box">
  <div class="space"></div>
  <p>
    Super Metroid Prime Fusion
  </p>
</div>
<div class="box">
  <div class="space"></div>
  <p>
    Resident Evil 2 Remake
  </p>
</div>
<div class="box">
  <div class="space"></div>
  <p>
    Yolo The Game
  </p>
</div>
<div class="box">
  <div class="space"></div>
  <p>
    Final Fantasy 7 Remake + All Additional DLC + Golden Tophat
  </p>
</div>
<div class="box">
  <div class="space"></div>
  <p>
    DerpVille
  </p>
</div>

JS 피들


7

@jake의 답변을 확장하면 전환이 최대 높이 값까지 계속 이동하여 매우 빠른 애니메이션이 발생합니다.

따라서 li : hover는 마우스가 상태에 들어간 후 마우스를 가져 오지 않은 속성의 전환이 마우스를 떠난 것입니다.

희망적으로 이것은 도움이 될 것입니다.

예 :

.sidemenu li ul {
   max-height: 0px;
   -webkit-transition: all .3s ease;
   -moz-transition: all .3s ease;
   -o-transition: all .3s ease;
   -ms-transition: all .3s ease;
   transition: all .3s ease;
}
.sidemenu li:hover ul {
    max-height: 500px;
    -webkit-transition: all 1s ease;
   -moz-transition: all 1s ease;
   -o-transition: all 1s ease;
   -ms-transition: all 1s ease;
   transition: all 1s ease;
}
/* Adjust speeds to the possible height of the list */

바이올린이 있습니다 : http://jsfiddle.net/BukwJ/


1
왜 이것이 -1인지 알 수 없습니다. 실제로 이것은 많은 자바 스크립트를 추가하는 사람들보다 더 나은 시도라고 생각합니다. 그것은 완벽한 해결책은 아니지만 약간의 조정으로 잘 작동합니다. 이것이 반환 값에 효과적이라는 것을 알았습니다. 전이 : 모든 500ms 큐빅 베 지어 (0.000, 1.225, 0.085, 0.385); 이것은 열 때 2 초 전환을 기반으로 한 다음 위의 코드는 초기 상태로 돌아갑니다. 고마워 ... 이것은 위의 모든 것보다 나에게 도움이되었습니다. +1 나는 베 지어 만들려면이 사이트를 사용 matthewlein.com/ceaser을
gcoulby

좋습니다. 조금 더 조정이 필요했습니다. 전이 : 모든 500ms 큐빅 베 지어 (0.000, 1.390, 0.000, 0.635); 전환이 5 %-100 % (실제로 최종 값은 약 28 % 임)에서 프로젝트에 따라 달라 지도록 지정해야합니다.
gcoulby

절대적으로 이상적인 것은 아니지만 평균 높이가 얼마인지에 대해 알고 있다면 빠른 수정입니다.
jamie

7

나는 정말 견고한 솔루션을 생각해 냈다고 생각합니다.

확인! 나는이 문제가 인터넷만큼 오래되었다는 것을 알고 있지만 mutant-transition이라는 플러그인으로 전환 한 솔루션이 있다고 생각 합니다. 내 솔루션 style=""은 DOM이 변경 될 때마다 추적 요소 의 속성을 설정합니다 . 결과적으로 전환에 좋은 ole CSS를 사용할 수 있으며 해키 픽스 또는 특수 자바 스크립트를 사용할 수 없습니다. 을 사용하여 문제가되는 요소를 추적 할 대상을 설정하기 만하면됩니다 data-mutant-attributes="X".

<div data-mutant-attributes="height">                                                                      
        This is an example with mutant-transition                                                                                                          
    </div>

그게 다야! 이 솔루션은 MutationObserver 를 사용 하여 DOM의 변경 사항을 따릅니다. 이로 인해 실제로 수동으로 애니메이션을 적용하기 위해 아무것도 설정하거나 javascript를 사용할 필요가 없습니다. 변경 사항은 자동으로 추적됩니다. 그러나 MutationObserver를 사용하기 때문에 IE11 +에서만 전환됩니다.

피들!


12
일반적으로 누군가가 "JavaScript없이"무언가를 수행하는 방법을 물을 때, JavaScript가 비활성화 된 브라우저에서 솔루션이 작동해야합니다. "나만의 스크립트를 작성하지 않고"라는 의미는 아닙니다. 자바 스크립트를 사용하지 않고 플러그인을 사용할 수 있다는 것은 자바 스크립트 플러그인이라는 점을 고려할 때 오해의 소지가 있습니다.
BoltClock

나는 당신이 특별한 자바 스크립트를 사용할 필요가 없다고 말할 때, 당신은 자바 스크립트를 작성할 필요가 없다는 것을 의미합니다 . JS 라이브러리를 포함시키고 HTML에서 보려는 속성을 지정하십시오. 고정 높이 CSS를 사용하거나 아무것도 알아낼 필요가 없습니다. 그냥 스타일과 이동합니다.
JonTroncoso

"(...) 실제로 아무것도 설정하거나 자바 스크립트를 사용하여 수동으로 애니메이션을 적용 할 필요가 없습니다 (...)"
Roko C. Buljan

6

다음은 노드별로 하드 코드를 설정하거나 초기화 할 사용자 코드없이 0을 포함한 시작 높이에서 자동 (전체 크기 및 유연성)으로 전환하는 방법입니다. https://github.com/csuwildcat / transition-auto . 이것은 기본적으로 당신이 원하는 것에 대한 성배입니다, 나는 믿습니다-> http://codepen.io/csuwldcat/pen/kwsdF . 다음 JS 파일을 페이지에 넣으면 reveal=""확장 및 축소하려는 노드에서 단일 부울 속성을 추가 / 제거하기 만하면 됩니다.

예제 코드 아래에있는 코드 블록을 포함 시키면 사용자로서해야 할 모든 것이 있습니다.

/*** Nothing out of the ordinary in your styles ***/
<style>
    div {
        height: 0;
        overflow: hidden;
        transition: height 1s;
    }
</style>

/*** Just add and remove one attribute and transition to/from auto! ***/

<div>
    I have tons of content and I am 0px in height you can't see me...
</div>

<div reveal>
     I have tons of content and I am 0px in height you can't see me...
     but now that you added the 'reveal' attribute, 
     I magically transitioned to full height!...
</div>

페이지에 포함 할 코드 블록은 다음과 같습니다.

이 JS 파일을 페이지에 놓으십시오. 모두 Just Works ™

/ * 높이 코드 : 자동; 전환 * /

(function(doc){

/* feature detection for browsers that report different values for scrollHeight when an element's overflow is hidden vs visible (Firefox, IE) */
var test = doc.documentElement.appendChild(doc.createElement('x-reveal-test'));
    test.innerHTML = '-';
    test.style.cssText = 'display: block !important; height: 0px !important; padding: 0px !important; font-size: 0px !important; border-width: 0px !important; line-height: 1px !important; overflow: hidden !important;';
var scroll = test.scrollHeight || 2;
doc.documentElement.removeChild(test);

var loading = true,
    numReg = /^([0-9]*\.?[0-9]*)(.*)/,
    skipFrame = function(fn){
      requestAnimationFrame(function(){
        requestAnimationFrame(fn);
      });
    },
    /* 2 out of 3 uses of this function are purely to work around Chrome's catastrophically busted implementation of auto value CSS transitioning */
    revealFrame = function(el, state, height){
        el.setAttribute('reveal-transition', 'frame');
        el.style.height = height;
        skipFrame(function(){
            el.setAttribute('reveal-transition', state);
            el.style.height = '';
        });
    },
    transitionend = function(e){
      var node = e.target;
      if (node.hasAttribute('reveal')) {
        if (node.getAttribute('reveal-transition') == 'running') revealFrame(node, 'complete', '');
      } 
      else {
        node.removeAttribute('reveal-transition');
        node.style.height = '';
      }
    },
    animationstart = function(e){
      var node = e.target,
          name = e.animationName;   
      if (name == 'reveal' || name == 'unreveal') {

        if (loading) return revealFrame(node, 'complete', 'auto');

        var style = getComputedStyle(node),
            offset = (Number(style.paddingTop.match(numReg)[1])) +
                     (Number(style.paddingBottom.match(numReg)[1])) +
                     (Number(style.borderTopWidth.match(numReg)[1])) +
                     (Number(style.borderBottomWidth.match(numReg)[1]));

        if (name == 'reveal'){
          node.setAttribute('reveal-transition', 'running');
          node.style.height = node.scrollHeight - (offset / scroll) + 'px';
        }
        else {
            if (node.getAttribute('reveal-transition') == 'running') node.style.height = '';
            else revealFrame(node, 'running', node.scrollHeight - offset + 'px');
        }
      }
    };

doc.addEventListener('animationstart', animationstart, false);
doc.addEventListener('MSAnimationStart', animationstart, false);
doc.addEventListener('webkitAnimationStart', animationstart, false);
doc.addEventListener('transitionend', transitionend, false);
doc.addEventListener('MSTransitionEnd', transitionend, false);
doc.addEventListener('webkitTransitionEnd', transitionend, false);

/*
    Batshit readyState/DOMContentLoaded code to dance around Webkit/Chrome animation auto-run weirdness on initial page load.
    If they fixed their code, you could just check for if(doc.readyState != 'complete') in animationstart's if(loading) check
*/
if (document.readyState == 'complete') {
    skipFrame(function(){
        loading = false;
    });
}
else document.addEventListener('DOMContentLoaded', function(e){
    skipFrame(function(){
        loading = false;
    });
}, false);

/* Styles that allow for 'reveal' attribute triggers */
var styles = doc.createElement('style'),
    t = 'transition: none; ',
    au = 'animation: reveal 0.001s; ',
    ar = 'animation: unreveal 0.001s; ',
    clip = ' { from { opacity: 0; } to { opacity: 1; } }',
    r = 'keyframes reveal' + clip,
    u = 'keyframes unreveal' + clip;

styles.textContent = '[reveal] { -ms-'+ au + '-webkit-'+ au +'-moz-'+ au + au +'}' +
    '[reveal-transition="frame"] { -ms-' + t + '-webkit-' + t + '-moz-' + t + t + 'height: auto; }' +
    '[reveal-transition="complete"] { height: auto; }' +
    '[reveal-transition]:not([reveal]) { -webkit-'+ ar +'-moz-'+ ar + ar +'}' +
    '@-ms-' + r + '@-webkit-' + r + '@-moz-' + r + r +
    '@-ms-' + u +'@-webkit-' + u + '@-moz-' + u + u;

doc.querySelector('head').appendChild(styles);

})(document);

/ * 데모 코드 * /

    document.addEventListener('click', function(e){
      if (e.target.nodeName == 'BUTTON') {
        var next = e.target.nextElementSibling;
        next.hasAttribute('reveal') ? next.removeAttribute('reveal') : next.setAttribute('reveal', '');
      }
    }, false);

9
이것은 제안 된 다른 솔루션보다 훨씬 깨끗하고 유연한 솔루션이지만 JS는 전혀 손대지 않아야한다고 생각합니다. 당신이 틀렸다고 말하는 것이 아니라 한숨입니다.
mystrdat

@mystrdat는 분명히, JS는 특정 조건을 감시하고 감시하는 이벤트 / 조건에 따라 몇 가지 속성 / 임시 CSS 값을 추가하는 데만 사용됩니다. 전환은 여전히 ​​CSS에서 모두 수행됩니다. 동의하지만,이 수준의 설정 및 핸드 홀딩이 겉보기에 간단한 사용 사례를 진정으로 만족시키는 것이 필요합니다! : /
csuwldcat 2018

1
@KarolisRamanauskas 아니오 그것은 문제가되지 않습니다-IE는 CSS Keyframe과 requestAnimationFrame을 모두 지원합니다. clip내 더미 속성 트리거 로 사용 하고 있었고 어떤 이유로 IE가 클립 애니메이션을 허용하지 않았습니다. 불투명으로 전환했으며 codepen.io/csuwldcat/pen/FpzGa 모두 다시 작동합니다 . 답변의 코드를 일치하도록 업데이트했습니다.
csuwldcat

1
@csuwldcat 아주 좋은 해결책, 내용이 조금씩 나타나고 사라지는 것을 알았습니다. 왜 이런 일이 발생합니까? 피할 수 있습니까?
Beto Aveiga

12
나는 이것을 높이고 싶지만 작동시키는 방법에 대한 질문에 대답하는 대신 작동하도록 플러그인을 공유했습니다. 궁금한 점은 플러그인을 리버스 엔지니어링하는 것입니다. 플러그인의 기능과 이유에 대한 자세한 설명을 포함하도록 답변을 업데이트하기를 바랍니다. 코드를보다 설명하기 쉽게 변경하십시오. 예를 들어 정적 CSS를 작성하는 전체 코드 섹션이 있습니다. 오히려 CSS를 생성하는 코드보다 CSS를보고 싶습니다. 모든 브라우저 접두사에 대해 반복하는 것처럼 지루한 부분을 제거 할 수 있습니다.
gilly3

6

최대 높이에 애니메이션을 적용하는 Jake의 답변은 훌륭하지만 최대 최대 높이를 설정하여 지연이 발생했습니다.

접을 수있는 내용을 내부 div로 옮기고 내부 div의 높이를 가져 와서 최대 높이를 계산할 수 있습니다 (JQuery를 통해 outerHeight () 일 수 있음).

$('button').bind('click', function(e) { 
  e.preventDefault();
  w = $('#outer');
  if (w.hasClass('collapsed')) {
    w.css({ "max-height": $('#inner').outerHeight() + 'px' });
  } else {
    w.css({ "max-height": "0px" });
  }
  w.toggleClass('collapsed');
});

다음은 jsfiddle 링크입니다. http://jsfiddle.net/pbatey/duZpT

다음은 최소한의 코드 만 필요한 jsfiddle입니다. http://jsfiddle.net/8ncjjxh8/


5

이 스레드가 오래되었다는 것을 알고 있지만 특정 Google 검색에서 순위가 ​​높아 업데이트 가치가 있다고 생각합니다.

또한 요소의 높이를 얻거나 설정하십시오.

var load_height = document.getElementById('target_box').clientHeight;
document.getElementById('target_box').style.height = load_height + 'px';

target_box의 닫는 태그 바로 다음에이 자바 스크립트를 인라인 스크립트 태그로 덤프해야합니다.


document.getElementById ( 'target_box'). getBoundingClientRect (). height가 가장 좋습니다.
변경

5

나는 이것을 할 수 있었다. 나는이 .child& A .parent사업부를. 자식 div는 absolute위치 와 함께 부모의 너비 / 높이에 완벽하게 맞습니다 . 그런 다음 translate속성에 애니메이션을 적용하여 Y값을 내립니다 100%. 매우 부드러운 애니메이션, 다른 솔루션과 마찬가지로 결함이나 아래쪽이 없습니다.

이와 같은 의사 코드

.parent{ position:relative; overflow:hidden; } 
/** shown state */
.child {
  position:absolute;top:0;:left:0;right:0;bottom:0;
  height: 100%;
  transition: transform @overlay-animation-duration ease-in-out;
  .translate(0, 0);
}

/** Animate to hidden by sliding down: */
.child.slidedown {
  .translate(0, 100%); /** Translate the element "out" the bottom of it's .scene container "mask" so its hidden */
}

heighton .parent, in px,을 지정 %하거나로 둡니다 auto. 그런 다음이 div는 .child아래로 미끄러질 때 div를가립니다.


이것의 실례는 대단히 감사하겠습니다.
신경 전달 물질

5

JavaScript로 답변을 게시하고 다운 투표를 받았으므로 성가신 다음 다시 시도하고 CSS로만 크랙했습니다!

이 솔루션은 몇 가지 '기술'을 사용합니다.

하지만 CSS 만 사용하여 성능 전환을 수행하고 전환을 원활하게 수행 할 수있는 단일 전환 기능이 있습니다. 성배!

물론 단점이 있습니다! 콘텐츠가 잘리는 너비를 제어하는 ​​방법을 알아낼 수 없습니다 ( overflow:hidden). 패딩 하단 해킹으로 인해 너비와 높이가 밀접하게 관련되어 있습니다. 그래도 방법이있을 수 있으므로 다시 올 것입니다.

https://jsfiddle.net/EoghanM/n1rp3zb4/28/

body {
  padding: 1em;
}

.trigger {
  font-weight: bold;
}

/* .expander is there for float clearing purposes only */
.expander::after {
  content: '';
  display: table;
  clear: both;
}

.outer {
  float: left; /* purpose: shrink to fit content */
  border: 1px solid green;
  overflow: hidden;
}

.inner {
  transition: padding-bottom 0.3s ease-in-out;  /* or whatever crazy transition function you can come up with! */
  padding-bottom: 0%;  /* percentage padding is defined in terms of width. The width at this level is equal to the height of the content */
  height: 0;

  /* unfortunately, change of writing mode has other bad effects like orientation of cursor */
  writing-mode: vertical-rl;
  cursor: default; /* don't want the vertical-text (sideways I-beam) */
  transform: rotate(-90deg) translateX(-100%);  /* undo writing mode */
  transform-origin: 0 0;
  margin: 0;  /* left/right margins here will add to height */
}

.inner > div { white-space: nowrap; }

.expander:hover .inner,  /* to keep open when expanded */
.trigger:hover+.expander .inner {
  padding-bottom: 100%;
}
<div class="trigger">HoverMe</div>
<div class="expander">
  <div class="outer">
    <div class="inner">
      <div>First Item</div>
      <div>Content</div>
      <div>Content</div>
      <div>Content</div>
      <div>Long Content can't be wider than outer height unfortunately</div>
      <div>Last Item</div>
    </div>
  </div>
</div>
<div>
  after content</div>
</div>


이것의 다른 단점은 커서를 항목 목록으로 이동하여 항목 목록으로 커서를 옮길 수 없기 때문에 (OP 요청의 이유), 툴팁 기능보다는 유용합니다. 예를 들어 중첩 된 하위 메뉴가있는 메뉴입니다.
TylerH

그것은 순전히 질문이 구성된 방식의 결과이며 기술과 관련이 없습니다. 원하는 경우 input[type="checkbox"]:checked대신 트리거를 트리거로 변경할 수 있습니다 :hover(예 : JavaScript를 사용하여 클래스를 추가하지 않으려는 경우)
EoghanM

나는 질문의 공식화 방법에 관계없이 솔루션의 구현이 너무 제한적이라면 해당 솔루션의 답변에 언급되어야합니다 (또는 바람직하게 설명 ). 이 솔루션은 '거룩한 성배'라고 언급하지만 전환 된 div를 가리킬 수도 없습니다 ... 나에게 그러한 궁극적 인 해결책은 아닙니다.
TylerH

안녕하세요 @TylerH, 사과합니다. 원래 질문의 트리거가 확장 된 목록을 둘러싼다는 사실을 놓쳤으므로 마우스를 가져 가면 목록이 열려 있어야합니다. 이것을 반영하여 답변을 업데이트했습니다. 앞서 언급했듯이, CSS에서만 가능하지 않은 새로운 기술을 제시하고 있기 때문에 어떻게 트리거되는지가 전부가 아닙니다 (몇 년 동안 해결책을 찾고 있습니다).
EoghanM

4

다음은 방금 jQuery와 함께 사용한 솔루션입니다. 이것은 다음 HTML 구조에서 작동합니다.

<nav id="main-nav">
    <ul>
        <li>
            <a class="main-link" href="yourlink.html">Link</a>
            <ul>
                <li><a href="yourlink.html">Sub Link</a></li>
            </ul>
        </li>
    </ul>
</nav>

그리고 기능 :

    $('#main-nav li ul').each(function(){
        $me = $(this);

        //Count the number of li elements in this UL
        var liCount = $me.find('li').size(),
        //Multiply the liCount by the height + the margin on each li
            ulHeight = liCount * 28;

        //Store height in the data-height attribute in the UL
        $me.attr("data-height", ulHeight);
    });

그런 다음 클릭 기능을 사용하여 높이를 설정하고 제거 할 수 있습니다 css()

$('#main-nav li a.main-link').click(function(){
    //Collapse all submenus back to 0
    $('#main-nav li ul').removeAttr('style');

    $(this).parent().addClass('current');

    //Set height on current submenu to it's height
    var $currentUl = $('li.current ul'),
        currentUlHeight = $currentUl.attr('data-height');
})

CSS :

#main-nav li ul { 
    height: 0;
    position: relative;
    overflow: hidden;
    opacity: 0; 
    filter: alpha(opacity=0); 
    -ms-filter: "alpha(opacity=0)";
    -khtml-opacity: 0; 
    -moz-opacity: 0;
    -webkit-transition: all .6s ease-in-out;
    -moz-transition: all .6s ease-in-out;
    -o-transition: all .6s ease-in-out;
    -ms-transition: all .6s ease-in-out;
    transition: all .6s ease-in-out;
}

#main-nav li.current ul {
    opacity: 1.0; 
    filter: alpha(opacity=100); 
    -ms-filter: "alpha(opacity=100)";
    -khtml-opacity: 1.0; 
    -moz-opacity: 1.0;
}

.ie #main-nav li.current ul { height: auto !important }

#main-nav li { height: 25px; display: block; margin-bottom: 3px }

이 최신 JQuery와 버전이 제대로 표시되지 않습니다
oliverbachmann

4

나는 최근에를 전환했습니다 max-heightli요소가 아닌 포장 ul.

추론은 소규모의 지연이 있다는 것입니다 max-heights대형에 비해 (전혀 경우) 훨씬 눈에 잘 띄지 않는 max-heights, 나는 또한 나의 설정할 수 있습니다 max-height받는 상대적인 값 font-sizeli사용에 의해 오히려 어떤 임의의 큰 수보다를 ems하거나 rems.

내 글꼴 크기가 1rem인 경우 (랩핑 된 텍스트를 수용하기 위해) max-height비슷한 것으로 설정 3rem합니다. 여기에서 예를 볼 수 있습니다.

http://codepen.io/mindfullsilence/pen/DtzjE


3

나는 모든 것을 자세히 읽지는 않았지만 최근 에이 문제가 있었고 다음과 같은 일을했습니다.

div.class{
   min-height:1%;
   max-height:200px;
   -webkit-transition: all 0.5s ease;
   -moz-transition: all 0.5s ease;
   -o-transition: all 0.5s ease;
   -webkit-transition: all 0.5s ease;
   transition: all 0.5s ease;
   overflow:hidden;
}

div.class:hover{
   min-height:100%;
   max-height:3000px;
}

이를 통해 처음에는 최대 200px 높이의 컨텐츠를 표시하는 div를 가질 수 있으며 호버의 크기는 적어도 div의 전체 컨텐츠만큼 커집니다. Div는 3000px가되지 않지만 3000px는 내가 부과하는 한계입니다. non : hover에서 전환해야합니다. 그렇지 않으면 이상한 렌더링이 발생할 수 있습니다. 이런 식으로 : hover는 : hover가 아닌 것을 상속합니다.

px에서 % 또는 자동으로 전환이 작동하지 않습니다. 동일한 측정 단위를 사용해야합니다. 이것은 나를 위해 잘 작동합니다. HTML5를 사용하면 완벽합니다 ...

항상 해결 방법이 있다는 것을 기억하십시오 ...; )

누군가가 이것을 유용하게 사용하기를 바랍니다.


3

제공된 하드 코딩 된 최대 높이 값이 실제 높이보다 크지 않은 경우 Jake의 최대 높이 솔루션이 제대로 작동합니다 (그렇지 않은 경우 지연 및 타이밍 문제가 발생하기 때문). 반면에 하드 코딩 된 값이 실수로 실제 높이보다 크지 않으면 요소가 완전히 열리지 않습니다.

다음 CSS 전용 솔루션에는 대부분의 실제 크기보다 커야하는 하드 코딩 된 크기가 필요합니다. 그러나 실제 크기가 하드 코딩 된 크기보다 큰 경우도 있습니다. 이 경우 전환이 약간 뛸 수 있지만 부분적으로 보이는 요소는 남기지 않습니다. 따라서이 솔루션은 알 수없는 콘텐츠 (예 : 데이터베이스)에서 콘텐츠가 일반적으로 x 픽셀보다 크지 않지만 예외가 있음을 알고있는 경우에도 사용할 수 있습니다.

아이디어는 margin-bottom (또는 약간 다른 애니메이션의 margin-top)에 음수 값을 사용하고 overflow : hidden을 사용하여 콘텐츠 요소를 중간 요소에 배치하는 것입니다. 내용 요소의 음수 여백은 중간 요소의 높이를 줄입니다.

다음 코드는 margin-bottom에서 -150px에서 0px 로의 전환을 사용합니다. content 요소가 150px보다 크지 않는 한 이것만으로도 잘 작동합니다. 또한 중간 요소의 최대 높이에서 0px에서 100 % 로의 전환을 사용합니다. content 요소가 150px보다 높으면 중간 요소가 숨겨집니다. 최대 높이의 경우 전환은 부드러운 시각적 효과가 아니라 닫을 때 응용 프로그램을 1 초 지연시키는 데 사용되므로 0px에서 100 %까지 실행할 수 있습니다.

CSS :

.content {
  transition: margin-bottom 1s ease-in;
  margin-bottom: -150px;
}
.outer:hover .middle .content {
  transition: margin-bottom 1s ease-out;
  margin-bottom: 0px
}
.middle {
  overflow: hidden;
  transition: max-height .1s ease 1s;
  max-height: 0px
}
.outer:hover .middle {
  transition: max-height .1s ease 0s;
  max-height: 100%
}

HTML :

<div class="outer">
  <div class="middle">
    <div class="content">
      Sample Text
      <br> Sample Text
      <br> Sample Text
      <div style="height:150px">Sample Test of height 150px</div>
      Sample Text
    </div>
  </div>
  Hover Here
</div>

마진 하단의 값은 음수 여야하며 가능한 한 콘텐츠 요소의 실제 높이와 비슷해야합니다. 그것이 절대 값이 크면 최대 높이 솔루션과 비슷한 지연 및 타이밍 문제가 있지만 하드 코딩 된 크기가 실제 크기보다 크지 않은 한 제한 될 수 있습니다. margin-bottom의 절대 값이 실제 높이보다 작 으면 tansition이 약간 점프합니다. 전환 후에는 콘텐츠 요소가 완전히 표시되거나 완전히 제거됩니다.

자세한 내용은 내 블로그 게시물 http://www.taccgl.org/blog/css_transition_display.html#combined_height를 참조하십시오.


3

클립 패스로 리버스 (축소) 애니메이션을 만들어이 작업을 수행 할 수 있습니다.

#child0 {
    display: none;
}
#parent0:hover #child0 {
    display: block;
    animation: height-animation;
    animation-duration: 200ms;
    animation-timing-function: linear;
    animation-fill-mode: backwards;
    animation-iteration-count: 1;
    animation-delay: 200ms;
}
@keyframes height-animation {
    0% {
        clip-path: polygon(0% 0%, 100% 0.00%, 100% 0%, 0% 0%);
    }
    100% {
        clip-path: polygon(0% 0%, 100% 0.00%, 100% 100%, 0% 100%);
    }
}
<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>


2

이것은 문제에 대한 "해결책"이 아니라 더 많은 해결 방법입니다. 텍스트로 작성된 대로만 작동하지만 필요에 따라 다른 요소와 작동하도록 변경할 수 있습니다.

.originalContent {
    font-size:0px;
    transition:font-size .2s ease-in-out;
}
.show { /* class to add to content */
    font-size:14px;
}

예를 들면 다음과 같습니다. http://codepen.io/overthemike/pen/wzjRKa

기본적으로 글꼴 크기를 0으로 설정하고 높이, 최대 높이 또는 scaleY () 등 대신 높이를 원하는 속도로 변환하기에 충분한 속도로 전환하십시오. CSS를 사용하여 실제 높이를 자동으로 변환하는 것은 현재 가능하지 않지만 내용을 변환하는 것은 글꼴 크기 전환입니다.

  • 참고-코드 펜에는 자바 스크립트가 있지만 아코디언을 클릭하면 CSS 클래스를 추가 / 제거하는 것이 유일한 목적입니다. 이것은 숨겨진 라디오 버튼으로 수행 할 수 있지만 높이 변환에만 초점을 두지 않았습니다.

1
이 답변을 효과적으로 복제 하지만 불투명-페이드 효과는 생략합니다.
SeldomNeedy

동의했다. 더 나은 접근 방식.
Mike S.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.