Câu hỏi Làm thế nào tôi có thể chuyển đổi chiều cao: 0; chiều cao: auto; sử dụng CSS?


Tôi đang cố gắng tạo ra <ul> trượt xuống bằng cách sử dụng chuyển tiếp CSS.

Các <ul> bắt đầu lúc height: 0;. Khi di chuột, chiều cao được đặt thành height:auto;. Tuy nhiên, điều này làm cho nó đơn giản xuất hiện, không phải chuyển đổi,

Nếu tôi làm điều đó từ height: 40px; đến height: auto;, sau đó nó sẽ trượt lên đến height: 0;, và sau đó đột nhiên nhảy đến độ cao chính xác.

Làm cách nào khác tôi có thể làm điều này mà không cần sử dụng 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>


1602
2017-08-18 02:50


gốc


Tôi tin rằng height:auto/max-height giải pháp sẽ chỉ hoạt động nếu bạn đang mở rộng diện tích lớn hơn height bạn muốn hạn chế. Nếu bạn có một max-height của 300px, nhưng hộp thả xuống hộp kết hợp, có thể trả về 50px, sau đó max-height sẽ không giúp bạn, 50px thay đổi tùy thuộc vào số lượng phần tử, bạn có thể đến một tình huống không thể xảy ra mà tôi không thể khắc phục được vì height không cố định, height:auto là giải pháp, nhưng tôi không thể sử dụng quá trình chuyển đổi với điều này. - Christopher Thomas
OP đang cố gắng giải pháp css, chứ không phải js, nếu không họ chỉ có thể sử dụng tràn và tạo hoạt ảnh - Toni Leigh
@ToniLeigh hoặc jQuery.slideToggle (); - mopo922
Tất cả những câu trả lời này không hoàn toàn "đúng" .... Tôi có một giải pháp (thêm câu trả lời ngày hôm nay) chỉ với hai khai báo CSS. Nó không sử dụng chiều cao tối đa. Đó là CSS thuần túy và siêu đơn giản để thiết lập. Hoạt động trên vị trí tương đối. Đây là một fiddle jsfiddle.net/n5XfG/2596 - VIDesignz
@VIDesignz: Nhưng lợi nhuận -100% của div bên trong nhận được chiều rộng của div bao bọc, không phải chiều cao. Vì vậy, giải pháp này có cùng một loại vấn đề, đó là giải pháp chiều cao tối đa. Hơn nữa khi chiều rộng nhỏ hơn chiều cao của nội dung, không phải tất cả nội dung đều bị ẩn bởi -100% lề trên cùng. Vì vậy, đây là một giải pháp sai. - GregTom


Các câu trả lời:


Sử dụng max-height trong việc chuyển đổi và không height. Và đặt giá trị trên max-height một cái gì đó lớn hơn hộp của bạn sẽ nhận được.

Xem Bản trình diễn JSFiddle được cung cấp bởi Chris Jordan trong một câu trả lời đây.

#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>


2161
2017-11-30 18:42



điều này hoạt động tuyệt vời! ngoại trừ có một sự chậm trễ khi nó bắt đầu, bởi vì nó bắt đầu cho chiều cao tối đa mà ban đầu là rất cao .. hmm, tôi nghĩ rằng điều này là hơi khó chịu - vsync
1 giải pháp tuyệt vời! Tốc độ chuyển đổi được tính toán là thời gian bạn chỉ định chuyển sang giá trị chiều cao tối đa ... nhưng do chiều cao sẽ nhỏ hơn chiều cao tối đa, việc chuyển đổi sang chiều cao thực tế sẽ diễn ra nhanh hơn (thường là đáng kể) so với thời gian được chỉ định. - kingjeffrey
Lưu ý rằng điều này có thể gây ra quá trình chuyển đổi xấu xí kết thúc khi bạn phải sử dụng các giá trị lớn hơn nhiều so với giá trị được tính toán thực tế. Tôi nhận thấy điều này trong khi cố gắng làm cho div phát triển từ 0 độ cao đến chiều cao nội dung thay đổi rất nhiều do kích thước màn hình khác nhau (2 dòng trên màn hình 2560x1440 của tôi so với 10 dòng trên điện thoại thông minh). Đối với điều này tôi đã kết thúc với js. - jpeltoniemi
Công việc tuyệt vời xung quanh - không phải giải pháp;) - acSlater
Đây là một giải pháp khá lười biếng. Tôi giả định OP muốn sử dụng chiều cao: tự động vì chiều cao mở rộng của vùng chứa là hơi khó lường. Giải pháp này sẽ gây ra sự chậm trễ trước khi hoạt ảnh hiển thị. Ngoài ra, thời lượng hiển thị của hoạt ảnh sẽ không thể đoán trước được. Bạn sẽ nhận được nhiều kết quả có thể đoán trước (và có khả năng mượt mà hơn) bằng cách tính toán chiều cao kết hợp của mỗi nút con của vùng chứa và sau đó giảm bớt thành giá trị độ cao chính xác. - Shawn Whinnery


Thay vào đó, bạn nên sử dụng scaleY.

HTML:

<p>Here (scaleY(1))</p>
<ul>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>

CSS:

ul {
    background-color: #eee;
    transform: scaleY(0);    
    transform-origin: top;
    transition: transform 0.26s ease;
}

p:hover ~ ul {
    transform: scaleY(1);
}

Tôi đã tạo một phiên bản đầu tiên của mã trên trên jsfiddle, http://jsfiddle.net/dotnetCarpenter/PhyQc/9/ và thay đổi jsfiddle của bạn để sử dụng scaleY thay vì chiều cao, http://jsfiddle.net/dotnetCarpenter/7cnfc/206/.


228
2018-06-23 10:57



Tôi upvoting câu trả lời này bởi vì nó hoạt động tốt trong các trình duyệt có khả năng chuyển đổi css3, nhưng cần lưu ý rằng điều này sẽ không hoạt động chút nào trong IE <9và sẽ không hoạt hình (nó sẽ chỉ nhảy) trong IE <10 - Hailwood
Phương pháp này chỉ một phần đạt được hiệu quả mong muốn nhưng không thực sự tẩy vũ trụ. Hộp chuyển đổi hoạt động như một phần tử tương đối được định vị - không gian được lấy lên bất kể nó được thu nhỏ như thế nào. Kiểm tra jsFiddle này trong đó có một đầu tiên của bạn và chỉ cần thêm một số văn bản không có thật ở phía dưới. Lưu ý cách văn bản bên dưới không di chuyển lên khi chiều cao hộp được chia tỷ lệ bằng không. - animuson♦
Bây giờ nó có: jsfiddle.net/gNDX3/1 Về cơ bản bạn cần phải tạo kiểu cho các yếu tố của bạn theo những gì bạn cần. Không có dấu đầu dòng hoặc tiện ích con như hành vi trong CSS / HTML. - dotnetCarpenter
Trong khi tôi hoan nghênh một người nào đó cố gắng tiếp cận khác nhau, hiệu ứng thế giới thực và các biến chứng mà giải pháp này mang lại còn tồi tệ hơn so với hack tối đa cao khủng khiếp. Xin đừng sử dụng. - mystrdat
Giãn cách thất bại jsfiddle.net/PhyQc/336 - e-info128


Bạn hiện không thể tạo hoạt ảnh trên chiều cao khi một trong những chiều cao liên quan là auto, bạn phải đặt hai chiều cao rõ ràng.


164
2017-08-18 12:46



Thường có nhiều cách để giải quyết vấn đề và không phải tất cả chúng đều phù hợp hoặc có thể. Tôi không biết tại sao @JedidiahHurt và Ryan Ore đang cố gắng hạn chế các câu trả lời có thể có trên trang web Hỏi & đáp. Đặc biệt là xem xét câu trả lời này là ở đây đầu tiên. Gấp đôi như vậy kể từ khi câu trả lời được chấp nhận là một cách giải quyết. - Hooray Im Helping
Câu trả lời từ @jake không thanh lịch cũng không chính xác. Câu trả lời được liên kết ở đây là tốt hơn nhiều. Nó hoạt động chính xác và xử lý mọi trường hợp kích thước - không thể nói về câu trả lời được chấp nhận. - GraphicsMuncher
Điều này có thay đổi không? Trong bootstrap ít hơn cho sụp đổ, tôi thấy họ rõ ràng chuyển chiều cao, và theo như tôi biết nó thích nghi với chiều cao bất kỳ: .collapsing { position: relative; height: 0; overflow: hidden; .transition-property(~"height, visibility"); .transition-duration(.35s); .transition-timing-function(ease); } - Andy
Oh, bạn biết đấy, tôi đặt cược bootstrap chỉ tính toán và đặt chiều cao trên nội dung ngay trước khi nó kích hoạt hoạt ảnh CSS ... - Andy
Yup: nó this.$element[dimension](this.$element[dimension]())[0].offsetHeight - Andy


Các giải pháp mà tôi đã luôn luôn được sử dụng là lần đầu tiên mờ dần, sau đó thu nhỏ font-size, padding và margin giá trị. Nó không giống như lau, nhưng nó hoạt động mà không cần tĩnh height hoặc là 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;
}

Ví dụ làm việc:

/* 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>

Spacing.


81
2018-05-29 14:05



Làm việc gọn gàng cho tôi. Không hoàn toàn giống như jQuery slideUp / Down. Bạn có thể thấy sự khác biệt chỉ với CPU yếu, như máy tính cũ hoặc thiết bị di động, đồng thời mở và đóng nhiều trong số chúng cùng một lúc. - Cruz Nunez
Nếu bạn có các nút hoặc bất kỳ phần tử không phải văn bản nào khác, bạn sẽ kết thúc với khoảng trắng không mong muốn trong khi không di chuột. - Dennis W
Bạn có thể tinh chỉnh thêm bằng cách chọn tất cả các phần tử con bằng * và áp dụng các thay đổi khác. Tuy nhiên, các nút nên bị ảnh hưởng bởi mã trên của tôi, nếu chúng được tạo kiểu đúng cách em. - Steven Vachon
Trong trường hợp của tôi, tôi cũng cần thêm line-height: 0; và border-width: 0; - Andrey Shatilov
Bạn không cần phải điều chỉnh line-height nếu bạn tránh đúng các đơn vị trên giá trị: developer.mozilla.org/en-US/docs/Web/CSS/… - Steven Vachon


Bạn có thể, với một chút trò đùa vui nhộn không phải ngữ nghĩa. Cách tiếp cận thông thường của tôi là làm sống động chiều cao của một DIV bên ngoài có một đứa trẻ duy nhất là một DIV ít phong cách chỉ được sử dụng để đo chiều cao nội dung.

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>

Người ta muốn chỉ có thể phân chia với .measuringWrapper và chỉ thiết lập chiều cao của DIV để tự động và có animate, nhưng điều đó dường như không hoạt động (chiều cao được thiết lập, nhưng không có hoạt hình xảy ra).

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>

Giải thích của tôi là cần có chiều cao rõ ràng để hoạt ảnh chạy. Bạn không thể có được hoạt ảnh ở độ cao khi chiều cao (chiều cao bắt đầu hoặc kết thúc) là auto.


64
2018-06-30 13:32



Vì điều này dựa trên javascript, bạn cũng có thể dễ dàng thêm measurWrapper bằng cách sử dụng javascript quá! - Quickredfox
Bạn có thể làm điều đó mà không có wrapper. Chỉ cần: function growDiv () {var growDiv = document.getElementById ('grow'); if (growDiv.clientHeight) {growDiv.style.height = 0; } else {growDiv.style.height = growDiv.scrollHeight + 'px'; }} - user1742529
Kiểm tra điều này ... nói về một câu trả lời đơn giản jsfiddle.net/n5XfG/2596 ... Câu trả lời của bạn vô cùng phức tạp vì không có lý do chính đáng. Không cần max-height, không cần autovà đặc biệt không cần Javascript! Chỉ cần hai tờ khai đơn giản - VIDesignz
@VIDesignz Bạn animate trên margin: 100%. Đây là 100% của chiều rộng của yếu tố, không phải chiều cao của nó! Điều này có nghĩa, nếu bạn có một phần tử có chiều cao lớn hơn chiều rộng của nó, điều này sẽ không ẩn nó. Ngoài ra, thực tế tốc độ hoạt ảnh hoàn toàn khác với tốc độ được xác định. - Timo Türschmann
Tôi rất vui mừng về câu trả lời của VIDesignz cho đến khi tôi đọc thêm về bình luận của Timo. Vâng, margin-top (và margin-bottomtương ứng với chiều rộng khi được xác định theo tỷ lệ phần trăm, có điều ngu ngốc, nhưng nó cũng giải thích lý do tại sao thời gian hoạt ảnh đóng và đóng lại hoàn toàn khác nhau - đó là điều bạn thấy trong câu trả lời được đánh giá cao nhất Chiều cao. Tại sao điều này khó làm như vậy? - Coderer


Tôi biết đây là câu trả lời thứ ba mươi cho câu hỏi này, nhưng tôi nghĩ nó xứng đáng với nó, vì vậy ở đây đi. Đây là một Chỉ CSS giải pháp với các thuộc tính sau:

  • Không có sự chậm trễ lúc đầu, và quá trình chuyển đổi không dừng lại sớm. Trong cả hai hướng (mở rộng và thu gọn), nếu bạn chỉ định thời lượng chuyển đổi là 300ms trong CSS của mình, thì quá trình chuyển đổi mất 300ms, dấu chấm.
  • Nó đang chuyển đổi chiều cao thực tế (không giống như transform: scaleY(0)), do đó, nó sẽ làm điều đúng nếu có nội dung sau phần tử có thể thu gọn.
  • Trong khi (như trong các giải pháp khác)  ma thuật số (như "chọn một chiều dài cao hơn hộp của bạn là bao giờ có được"), nó không gây tử vong nếu giả định của bạn kết thúc là sai. Quá trình chuyển đổi có thể không trông tuyệt vời trong trường hợp đó, nhưng trước và sau khi chuyển đổi, đây không phải là vấn đề: Trong phần mở rộng (height: auto), toàn bộ nội dung luôn có chiều cao chính xác (không giống như ví dụ: nếu bạn chọn max-heighthóa ra là quá thấp). Và trong trạng thái sụp đổ, chiều cao bằng 0.

Bản giới thiệu

Dưới đây là một bản demo với ba yếu tố đóng mở, tất cả các chiều cao khác nhau, tất cả đều sử dụng cùng một CSS. Bạn có thể muốn nhấp vào "trang đầy đủ" sau khi nhấp vào "đoạn mã chạy". Lưu ý rằng JavaScript chỉ chuyển đổi collapsed Lớp CSS, không có sự đo lường nào liên quan. (Bạn có thể thực hiện bản trình diễn chính xác này mà không cần bất kỳ JavaScript nào bằng cách sử dụng hộp kiểm hoặc :target). Cũng lưu ý rằng một phần của CSS chịu trách nhiệm cho quá trình chuyển đổi khá ngắn và HTML chỉ yêu cầu một phần tử trình bao bổ sung duy nhất.

$(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>

Làm thế nào nó hoạt động?

Có thực tế hai quá trình chuyển đổi liên quan đến việc thực hiện điều này. Một trong số đó chuyển đổi margin-bottom từ 0px (ở trạng thái mở rộng) đến -2000px trong trạng thái thu gọn (tương tự như câu trả lời này). 2000 đây là số ma thuật đầu tiên, nó dựa trên giả định rằng hộp của bạn sẽ không cao hơn này (2000 pixel có vẻ giống như một sự lựa chọn hợp lý).

Sử dụng margin-bottom bản thân quá trình chuyển đổi có hai vấn đề:

  • Nếu bạn thực sự có một hộp cao hơn 2000 pixel, thì margin-bottom: -2000px sẽ không ẩn mọi thứ - sẽ có nội dung hiển thị ngay cả trong trường hợp thu gọn. Đây là một sửa chữa nhỏ mà chúng tôi sẽ làm sau này.
  • Nếu hộp thực tế cao hơn 1000 pixel và quá trình chuyển đổi của bạn dài 300 m, thì có thể nhìn thấy quá trình chuyển đổi đã kết thúc sau khoảng 150ms (hoặc, theo hướng ngược lại, bắt đầu trễ 150ms).

Sửa vấn đề thứ hai này là nơi chuyển tiếp thứ hai đến, và quá trình chuyển đổi này nhắm mục tiêu khái niệm của trình bao bọc tối thiểu chiều cao ("khái niệm" bởi vì chúng tôi không thực sự sử dụng min-height tài sản cho việc này; thêm về điều đó sau).

Dưới đây là một hình ảnh động cho thấy cách kết hợp chuyển tiếp lề dưới với chuyển đổi chiều cao tối thiểu, cả hai thời gian bằng nhau, cho chúng ta một sự chuyển đổi kết hợp từ chiều cao đầy đủ đến chiều cao bằng không có cùng thời lượng.

animation as described above

Thanh bên trái cho thấy cách lề dưới tiêu cực đẩy đáy lên trên, giảm chiều cao nhìn thấy được. Thanh giữa cho biết chiều cao tối thiểu đảm bảo rằng trong trường hợp sụp đổ, quá trình chuyển đổi không kết thúc sớm và trong trường hợp mở rộng, quá trình chuyển đổi không bắt đầu muộn. Thanh bên phải cho thấy sự kết hợp của hai làm cho hộp chuyển đổi từ chiều cao đầy đủ thành độ cao bằng không trong khoảng thời gian chính xác.

Đối với bản demo của tôi, tôi đã giải quyết trên 50px là giá trị chiều cao tối thiểu trên. Đây là số ma thuật thứ hai, và nó phải thấp hơn chiều cao của hộp sẽ là bao giờ. 50px có vẻ hợp lý; có vẻ như bạn không muốn làm một yếu tố có thể đóng được mà thậm chí không cao tới 50 pixel ngay từ đầu.

Như bạn có thể thấy trong hoạt ảnh, quá trình chuyển đổi kết quả là liên tục, nhưng nó không có khả năng phân biệt - tại thời điểm khi chiều cao tối thiểu bằng với chiều cao đầy đủ được điều chỉnh bởi lề dưới, có sự thay đổi đột ngột về tốc độ. Điều này là rất đáng chú ý trong các hình ảnh động bởi vì nó sử dụng một chức năng thời gian tuyến tính cho cả hai quá trình chuyển đổi, và bởi vì toàn bộ quá trình chuyển đổi rất chậm. Trong trường hợp thực tế (bản demo của tôi ở trên cùng), quá trình chuyển đổi chỉ mất 300ms và quá trình chuyển đổi lề dưới không phải là tuyến tính. Tôi đã chơi xung quanh với rất nhiều chức năng thời gian khác nhau cho cả hai quá trình chuyển đổi, và những cái tôi đã kết thúc với cảm thấy như họ làm việc tốt nhất cho nhiều trường hợp rộng nhất.

Hai vấn đề vẫn còn cần khắc phục:

  1. điểm từ trên cao, nơi các hộp có chiều cao hơn 2000 pixel không được ẩn hoàn toàn trong trạng thái thu gọn,
  2. và vấn đề ngược lại, trong trường hợp không ẩn, các hộp có chiều cao dưới 50 pixel quá cao ngay cả khi quá trình chuyển đổi không chạy, vì chiều cao tối thiểu giữ chúng ở 50 pixel.

Chúng tôi giải quyết vấn đề đầu tiên bằng cách cho phần tử vùng chứa max-height: 0 trong trường hợp thu gọn, với 0s 0.3s chuyển đổi. Điều này có nghĩa rằng nó không thực sự là một quá trình chuyển đổi, nhưng max-height được áp dụng với độ trễ; nó chỉ áp dụng khi quá trình chuyển đổi kết thúc. Để điều này hoạt động chính xác, chúng tôi cũng cần chọn một số max-height đối diện, không bị sụp đổ, trạng thái. Nhưng không giống như trong trường hợp 2000px, khi việc chọn quá lớn của một số ảnh hưởng đến chất lượng của quá trình chuyển đổi, trong trường hợp này, nó thực sự không quan trọng. Vì vậy, chúng tôi chỉ có thể chọn một con số cao đến nỗi chúng tôi biết rằng không có chiều cao nào sẽ đến gần với điều này. Tôi đã chọn một triệu điểm ảnh. Nếu bạn cảm thấy bạn có thể cần hỗ trợ nội dung có chiều cao hơn một triệu pixel, thì 1) Tôi xin lỗi và 2) chỉ cần thêm một vài số không.

Vấn đề thứ hai là lý do tại sao chúng tôi không thực sự sử dụng min-height cho quá trình chuyển đổi chiều cao tối thiểu. Thay vào đó, có một ::after phần tử giả trong vùng chứa với một height chuyển đổi từ 50px thành 0. Điều này có tác dụng tương tự như min-height: Nó sẽ không cho phép thùng chứa co lại dưới bất kỳ chiều cao nào mà phần tử giả hiện có. Nhưng bởi vì chúng tôi đang sử dụng height, không phải min-height, bây giờ chúng ta có thể sử dụng max-height (một lần nữa áp dụng với độ trễ) để đặt chiều cao thực tế của phần tử giả thành 0 khi quá trình chuyển đổi kết thúc, đảm bảo rằng ít nhất bên ngoài quá trình chuyển đổi, thậm chí các phần tử nhỏ có chiều cao chính xác. Bởi vì min-height Là mạnh mẽ hơn hơn max-height, điều này sẽ không hiệu quả nếu chúng ta sử dụng min-height thay vì phần tử giả height. Cũng giống như max-height trong đoạn trước, điều này max-height cũng cần một giá trị cho kết thúc ngược lại của quá trình chuyển đổi. Nhưng trong trường hợp này, chúng tôi chỉ có thể chọn 50px.

Được thử nghiệm trong Chrome (Win, Mac, Android, iOS), Firefox (Win, Mac, Android), Edge, IE11 (ngoại trừ vấn đề bố cục flexbox với bản trình diễn của tôi mà tôi không bận tâm gỡ lỗi) và Safari (Mac, iOS ). Nói về flexbox, bạn có thể thực hiện công việc này mà không cần sử dụng bất kỳ flexbox nào; trong thực tế, tôi nghĩ bạn có thể làm cho hầu hết mọi thứ hoạt động trong IE7 - ngoại trừ thực tế là bạn sẽ không có chuyển tiếp CSS, làm cho nó trở thành một bài tập khá vô nghĩa.


45
2018-05-14 14:33



Tôi ước bạn có thể rút ngắn (đơn giản hóa) giải pháp của bạn hoặc ít nhất là ví dụ về mã - có vẻ như 90% ví dụ mã không liên quan đến câu trả lời của bạn. - Gil Epshtain


Một giải pháp trực quan để làm nổi bật chiều cao bằng cách sử dụng chuyển tiếp CSS3 là tạo hiệu ứng đệm thay thế.

Bạn không hoàn toàn có được hiệu ứng quét hoàn toàn, nhưng việc chơi xung quanh với các giá trị thời gian chuyển tiếp và giá trị đệm sẽ giúp bạn đủ gần. Nếu bạn không muốn đặt chiều cao / chiều cao tối đa rõ ràng, đây sẽ là những gì bạn đang tìm kiếm.

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/ (riffed off stephband's trên jsFiddle)


44
2018-06-26 19:05



Tôi nghĩ đây là câu trả lời hay nhất. Kỹ thuật này có thể mở rộng để điều chỉnh padding trên trẻ em là tốt. Trong trường hợp của tôi, tôi đã có thể kết hợp nó với các chuyển tiếp chiều cao rõ ràng trên một số nội dung được tiết lộ, và hiệu quả tổng thể thành công hơn nhiều so với chiều cao tối đa, điều này tốt cho việc tiết lộ nhưng giới thiệu một khoảnh khắc khó xử trì hoãn ẩn. Tôi sẽ sớm không làm động chút nào hơn là giới thiệu một sự chậm trễ vô nghĩa khiến ứng dụng của tôi dường như không phản hồi. Tôi ngạc nhiên quá nhiều người dường như nghĩ rằng đó là chấp nhận được. - Semicolon
Ngoại trừ rằng ở đây bạn không phải là animating chiều cao ở tất cả. Bạn đang làm động các padding ... nó có thể biến mất tốt bởi vì nó có thể sinh động từ trạng thái hiện tại xuống 0, nhưng nếu bạn quan sát kỹ khi nó mở rộng nó bật mở với văn bản và sau đó padding chỉ hoạt hình .. bởi vì nó không 't biết làm thế nào để animate từ 0 để tự động .... nó cần một phạm vi số ... đó là cách tweening hoạt động. - Rob R
Đây là một cách giải quyết tốt mà không phải là hacky. Đó không phải là câu trả lời hay nhất cho điều này câu hỏi, nhưng đó là một cách thay thế có hiệu quả đối với tôi. Đôi khi bạn chỉ cần hiệu ứng của một số hoạt hình chiều cao, không phải là hình ảnh động đầy đủ :) - Ivan Durst
Giải pháp này cũng không thành công khi sử dụng độ trễ chuyển tiếp. - Michel Joanisse
Tôi cũng đồng ý rằng giải pháp này là một giải pháp dọn dẹp sạch sẽ cung cấp các chuyển đổi khá chất lỏng nếu hoạt ảnh của bạn đủ nhanh (trong trường hợp của tôi cho một accordion với các chuyển đổi 0.1s nó là hoàn hảo!). Nó sẽ không có nhiều ứng dụng mặc dù, nhưng cũng không phải là các anwsers khác cho câu hỏi này! - Remi D


Cách giải quyết của tôi là chuyển đổi chiều cao tối đa thành chiều cao nội dung chính xác cho hoạt ảnh mượt mà, sau đó sử dụng chuyển đổiEnd gọi lại để đặt chiều cao tối đa thành 9999px để nội dung có thể thay đổi kích thước một cách tự do.

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>


43
2018-03-19 00:44



@ Derija93 Đó là bằng cách sử dụng hình ảnh động cũ hết hạn javascript cũ. Thách thức là sử dụng quá trình chuyển đổi CSS3 thay thế. - Adam
Vâng, vâng. Nhưng tại sao bạn sẽ sử dụng "chuyển tiếp CSS3 thay thế" nếu bạn, trong ví dụ của bạn, đã sử dụng jQuery, một thư viện, cung cấp rất nhiều "viết ít hơn, làm nhiều hơn" mã nào? Tôi muốn chỉ ra rằng phiên bản của bạn có thể trông tốt hơn nhiều, mặc dù phức tạp hơn, nếu nó KHÔNG sử dụng jQuery để nó có thể chạy trên hầu như bất kỳ trang web nào. Tôi đoán tôi đã nói rất sai. Xin lỗi vì việc đó. ;) - Kiruse
@ Derija93 Có lẽ vì quá trình chuyển đổi CSS3 có (theo tất cả các nguồn tôi có thể tìm thấy) hiệu suất tốt hơn nhiều so với hoạt ảnh jQuery. (Thực sự là vấn đề cực kỳ quan trọng đối với trường hợp sử dụng hiện tại của tôi, điều này đã mang tôi đến đây.) - Mark Amery
@ Derija93 'Nguyên nhân Hoạt ảnh Javascript chạy chậm so với quá trình chuyển đổi CSS3 bro và với hoạt ảnh jQuery bạn phải lo lắng về vòng lặp hoạt ảnh. Animate một cái gì đó trên nhấp chuột, sau đó nhấp vào nhanh chóng và xem như hình ảnh động lặp lại mình. Điều này được xử lý bằng CSS3. - Dropped.on.Caprica
@ Dropped.on.Caprica Đây là một chút cũ bây giờ. Tôi đã nói rằng tôi hiểu nhầm khái niệm mà anh ấy đang cố gắng chứng minh. Dù sao, đối với hoạt ảnh đơn giản, .stop làm các trick cho vấn đề vòng lặp hoạt hình khá phức tạp. Bây giờ khi bạn tạo hiệu ứng chiều cao và màu sắc nhưng chỉ muốn làm gián đoạn hoạt ảnh chiều cao, mọi thứ trở nên phức tạp hơn một chút ... Tôi nhận được quan điểm của bạn. - Kiruse