ฉันจะเปลี่ยนความสูงได้อย่างไร: 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 กำลังพยายามหาวิธีแก้ปัญหา css ไม่ใช่ js มิฉะนั้นพวกเขาสามารถใช้มากเกินไปและทำให้เคลื่อนไหวได้
Toni Leigh

5
@VIDesignz: แต่ส่วนขอบด้านใน -100% ได้รับความกว้างของ div wrapper ไม่ใช่ความสูง ดังนั้นวิธีนี้มีปัญหาแบบเดียวกันนั่นคือวิธีแก้ปัญหาความสูงสูงสุด ยิ่งไปกว่านั้นเมื่อความกว้างมีขนาดเล็กกว่าความสูงของเนื้อหาเนื้อหาทั้งหมดจะไม่ถูกซ่อนด้วย -100% ของระยะขอบ ดังนั้นนี่คือทางออกที่ผิด
GregTom

1
ดูgithub.com/w3c/csswg-drafts/issues/626สำหรับการอภิปรายรอบข้อมูลจำเพาะและการดำเนินการของการแก้ปัญหาที่เหมาะสม
เบนครีซี่

คำตอบ:


2745

ใช้ในการเปลี่ยนแปลงและไม่max-height heightและตั้งค่าmax-heightสิ่งที่ใหญ่กว่ากล่องของคุณจะได้รับ

ดูตัวอย่างของ JSFiddleจาก Chris Jordan ในคำตอบอื่นที่นี่

#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
มันใช้งานได้ดี! ยกเว้นมีความล่าช้าเมื่อมันเริ่มเพราะมันเริ่มต้นสำหรับความสูงสูงสุดซึ่งตอนแรกสูงมาก .. hmm ฉันคิดว่ามันค่อนข้างน่ารำคาญ
vsync

175
+1 สุดยอดทางออก! ความเร็วของการเปลี่ยนแปลงถูกคำนวณตามเวลาที่คุณระบุให้เปลี่ยนเป็นค่าความสูงสูงสุด ... แต่เนื่องจากความสูงจะน้อยกว่าความสูงสูงสุดการเปลี่ยนเป็นความสูงจริงจะเกิดขึ้นเร็วกว่า เวลาที่ระบุ
kingjeffrey

50
โปรดทราบว่าสิ่งนี้อาจทำให้การเปลี่ยนแปลงที่น่าเกลียดสิ้นสุดลงเมื่อคุณต้องใช้ค่าที่มากกว่าค่าที่คำนวณได้จริง ฉันสังเกตสิ่งนี้ในขณะที่พยายามทำให้ div เติบโตจากความสูง 0 ถึงความสูงของเนื้อหาที่แตกต่างกันอย่างมากเนื่องจากขนาดหน้าจอที่แตกต่างกัน (2 บรรทัดบนหน้าจอ 2560x1440 ของฉันเทียบกับ> 10 บรรทัดบนสมาร์ทโฟน) สำหรับเรื่องนี้ฉันไปกับ js
jpeltoniemi

44
วิธีแก้ปัญหาที่น่าเกลียดมากเพราะมันสร้างความล่าช้าในทิศทางเดียว แต่ไม่ใช่ในทิศทางอื่น
ทิม

84
นี่เป็นทางออกที่ค่อนข้างขี้เกียจ ฉันสมมติว่า OP ต้องการใช้ความสูง: อัตโนมัติเนื่องจากความสูงที่เพิ่มขึ้นของคอนเทนเนอร์ค่อนข้างคาดเดาไม่ได้ วิธีนี้จะทำให้เกิดความล่าช้าก่อนที่ภาพเคลื่อนไหวจะปรากฏ นอกจากนี้ช่วงเวลาที่มองเห็นได้ของภาพเคลื่อนไหวจะไม่สามารถคาดเดาได้ คุณจะได้รับผลลัพธ์ที่คาดการณ์ได้มากขึ้น (และน่าจะราบรื่นกว่า) โดยการคำนวณความสูงรวมของแต่ละโหนดลูกของคอนเทนเนอร์และจากนั้นทำให้ค่าความสูงถูกต้อง
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
ฉัน upvoting คำตอบนี้เพราะมันทำงานได้ดีในเบราว์เซอร์ที่มีคุณสมบัติ css3-transition แต่ควรสังเกตว่ามันจะไม่ทำงานเลยใน IE <9และจะไม่เคลื่อนไหว (มันจะกระโดด) ใน IE <10
Hailwood

215
วิธีนี้ได้ผลบางส่วนเท่านั้น แต่ไม่ได้ลบพื้นที่ กล่องที่ถูกเปลี่ยนรูปนั้นทำหน้าที่เหมือนองค์ประกอบที่ค่อนข้างอยู่ในตำแหน่ง - พื้นที่นั้นถูกยึดไว้ไม่ว่ามันจะถูกปรับขนาดอย่างไร ตรวจสอบjsFiddle นี้ที่ใช้อันแรกของคุณและเพิ่งเพิ่มข้อความปลอมที่ด้านล่าง โปรดทราบว่าข้อความด้านล่างจะไม่เลื่อนขึ้นเมื่อความสูงของกล่องถูกปรับเป็นศูนย์
animuson

9
ตอนนี้ก็ทำ: jsfiddle.net/gNDX3/1โดยทั่วไปคุณต้องจัดองค์ประกอบของคุณตามสิ่งที่คุณต้องการ ไม่มีสัญลักษณ์แสดงหัวข้อย่อยเงินหรือเครื่องมือเช่นพฤติกรรมใน CSS / HTML
dotnetCarpenter

70
ในขณะที่ฉันปรบมือใครบางคนที่พยายามใช้วิธีที่แตกต่างกันผลกระทบและภาวะแทรกซ้อนในโลกแห่งความเป็นจริงการแก้ปัญหานี้นำมาซึ่งแย่กว่าการแฮ็กความสูงสูงสุดที่น่ากลัวอยู่แล้ว กรุณาอย่าใช้
mystrdat

2
@SquareCat ไม่เป็นไร นี่คือสิ่งที่เป็นลิ้นชักมากขึ้นเช่น: jsfiddle.net/dotnetCarpenter/WTL2r
dotnetCarpenter

202

ขณะนี้คุณไม่สามารถสร้างความสูงได้เมื่อความสูงอย่างใดอย่างหนึ่งเกี่ยวข้องautoคุณต้องกำหนดความสูงอย่างชัดเจนสองระดับ


12
มักจะมีหลายวิธีในการแก้ปัญหาและไม่ใช่ทั้งหมดที่เหมาะสมหรือเป็นไปได้ ฉันไม่รู้ว่าทำไม @JedidiahHurt และ Ryan Ore พยายาม จำกัด คำตอบที่เป็นไปได้ในไซต์ถาม & ตอบ โดยเฉพาะการพิจารณาคำตอบนี้อยู่ที่นี่ก่อน ทวีคูณดังนั้นตั้งแต่คำตอบที่ยอมรับได้เป็นวิธีแก้ปัญหา
Hooray Im ช่วย

5
คำตอบจาก @jake นั้นไม่สวยงามและไม่ถูกต้อง คำตอบที่เชื่อมโยงที่นี่ดีกว่ามาก มันทำงานได้อย่างถูกต้องและจัดการกับทุกขนาด - ไม่สามารถพูดถึงคำตอบที่ยอมรับได้
GraphicsMuncher

5
Yup: ทำได้this.$element[dimension](this.$element[dimension]())[0].offsetHeight
Andy

4
มีการวางแผนเพื่อแก้ไขปัญหานี้หรือไม่? ฉันหมายความว่านี่เป็นเรื่องธรรมดาที่คาดว่าจะสามารถเปลี่ยนจากความสูง 0 เป็นauto...
Augustin Riedinger

6
@Meliodas "ไม่ใช่ / คุณไม่สามารถ" เป็นคำตอบที่ถูกต้องและเป็นที่ยอมรับสำหรับคำถามเกี่ยวกับ Stack Overflow
TylerH

122

วิธีการแก้ปัญหาที่ผมเคยใช้เสมอก็จะจางหายออกไปก่อนแล้วหดfont-size, paddingและmarginค่า มันไม่ได้มีลักษณะเช่นเดียวกับเช็ด แต่การทำงานโดยไม่คงที่หรือheightmax-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 คุณสามารถเห็นความแตกต่างเฉพาะกับ CPU ที่อ่อนแอเช่นคอมพิวเตอร์เก่าหรือมือถือและการเปิดและปิดหลาย ๆ อย่างในเวลาเดียวกัน
Cruz Nunez

3
หากคุณมีปุ่มหรือองค์ประกอบที่ไม่ใช่ข้อความอื่น ๆ คุณจะพบช่องว่างที่ไม่ต้องการขณะไม่วางเมาส์
Dennis W

3
คุณสามารถปรับแต่งเพิ่มเติมได้โดยเลือกองค์ประกอบลูกทั้งหมดด้วย*และใช้การเปลี่ยนแปลงอื่น ๆ ปุ่มควรจะได้รับผลกระทบจากโค้ดข้างต้นของฉัน emแต่ถ้าพวกเขาถูกเรียกขานอย่างถูกต้องกับ
Steven Vachon

1
ในกรณีของฉันฉันต้องเพิ่มline-height: 0;และborder-width: 0;
Andrey Shatilov

1
คุณไม่จำเป็นต้องปรับline-heightถ้าคุณหลีกเลี่ยงหน่วยที่ถูกต้องเกี่ยวกับค่า: developer.mozilla.org/en-US/docs/Web/CSS//
Steven Vachon

93

ฉันรู้ว่านี่เป็นคำตอบที่สามสิบสิ่งสำหรับคำถามนี้ แต่ฉันคิดว่ามันคุ้มค่าดังนั้นที่นี่ไป นี่เป็นโซลูชันCSS เท่านั้นที่มีคุณสมบัติต่อไปนี้:

  • ไม่มีความล่าช้าในการเริ่มต้นและการเปลี่ยนแปลงไม่หยุดเร็ว ในทั้งสองทิศทาง (การขยายและการยุบ) หากคุณระบุระยะเวลาการเปลี่ยน 300ms ใน CSS ของคุณการเปลี่ยนแปลงจะใช้เวลา 300ms ระยะเวลา
  • มันเปลี่ยนความสูงจริง (ไม่เหมือนtransform: scaleY(0)) ดังนั้นมันจะทำในสิ่งที่ถูกต้องหากมีเนื้อหาหลังจากองค์ประกอบที่ยุบได้
  • ในขณะที่ (เช่นในการแก้ปัญหาอื่น ๆ ) มีตัวเลขเวทย์มนตร์ (เช่น "เลือกความยาวที่สูงกว่ากล่องของคุณจะเป็น") มันไม่ร้ายแรงหากสมมติฐานของคุณจบลงด้วยการผิด การเปลี่ยนแปลงอาจไม่ได้ดูน่าทึ่งในกรณีนั้น แต่ก่อนและหลังการเปลี่ยนแปลงนี่ไม่ใช่ปัญหา: ในสถานะที่ขยาย ( height: auto) เนื้อหาทั้งหมดจะมีความสูงที่ถูกต้องเสมอ (ซึ่งแตกต่างจากเช่นถ้าคุณเลือกmax-heightที่จะกลายเป็น ต่ำเกินไป). และในสถานะที่ยุบตัวความสูงเป็นศูนย์เท่าที่ควร

การสาธิต

นี่คือตัวอย่างขององค์ประกอบสามอย่างที่ยุบได้ซึ่งมีความสูงต่างกันทั้งหมดที่ใช้ CSS เดียวกัน คุณอาจต้องการคลิก "เต็มหน้า" หลังจากคลิก "เรียกใช้ตัวอย่าง" โปรดทราบว่า JavaScript จะสลับcollapsedคลาส CSS เท่านั้นไม่มีการวัดที่เกี่ยวข้อง (คุณสามารถทำการสาธิตที่แน่นอนนี้โดยไม่ใช้ 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-bottomจาก 0px (ในสถานะขยาย) เป็น-2000pxอยู่ในสถานะยุบ (คล้ายกับคำตอบนี้ ) 2000 นี่คือหมายเลขเวทย์มนตร์แรกมันขึ้นอยู่กับสมมติฐานว่ากล่องของคุณจะไม่สูงกว่านี้ (2,000 พิกเซลดูเหมือนจะเป็นตัวเลือกที่สมเหตุสมผล)

การใช้การmargin-bottomเปลี่ยนแปลงเพียงอย่างเดียวมีสองประเด็น:

  • หากคุณมีกล่องที่สูงกว่า 2,000 พิกเซลจริง ๆ กล่องmargin-bottom: -2000pxจะไม่ซ่อนทุกอย่าง - จะมีสิ่งที่มองเห็นแม้ในกรณีที่ยุบ นี่เป็นการแก้ไขเล็กน้อยที่เราจะทำในภายหลัง
  • หากกล่องจริงบอกว่าสูง 1,000 พิกเซลและการเปลี่ยนของคุณมีความยาว300 มิลลิวินาทีการเปลี่ยนแปลงที่มองเห็นได้จะสิ้นสุดลงหลังจากผ่านไปประมาณ 150 มิลลิวินาที (หรือในทิศทางตรงกันข้ามจะเริ่มช้ากว่า 150 มิลลิวินาที)

การแก้ไขปัญหาที่สองนี้เป็นที่ที่การเปลี่ยนแปลงครั้งที่สองเข้ามาและการเปลี่ยนแปลงนี้จะกำหนดเป้าหมายตามความสูงต่ำสุดของเสื้อคลุม("แนวความคิด" เพราะเราไม่ได้ใช้min-heightคุณสมบัติสำหรับสิ่งนี้จริง ๆ

นี่คือภาพเคลื่อนไหวที่แสดงให้เห็นว่าการรวมการเปลี่ยนแปลงระยะขอบล่างกับการเปลี่ยนความสูงขั้นต่ำทั้งสองช่วงเวลาเท่ากันทำให้เรามีการเปลี่ยนแปลงรวมกันจากความสูงเต็มเป็นศูนย์ความสูงที่มีระยะเวลาเท่ากัน

ภาพเคลื่อนไหวตามที่อธิบายไว้ข้างต้น

แถบด้านซ้ายแสดงให้เห็นว่าระยะขอบด้านล่างติดลบนั้นผลักด้านล่างขึ้นด้านบนอย่างไรเพื่อลดความสูงที่มองเห็นได้ แถบกลางแสดงให้เห็นว่าระดับความสูงขั้นต่ำช่วยให้มั่นใจได้อย่างไรว่าในกรณีการยุบการเปลี่ยนแปลงยังไม่จบลงและในกรณีขยายการเปลี่ยนแปลงจะไม่เริ่มช้า แถบด้านขวาแสดงให้เห็นว่าการรวมกันของทั้งสองทำให้กล่องเปลี่ยนจากความสูงเต็มเป็นศูนย์ในเวลาที่ถูกต้อง

สำหรับการสาธิตของฉันฉันได้ตัดสินที่ 50px เป็นค่าความสูงขั้นต่ำด้านบน นี่คือหมายเลขเวทย์มนตร์ที่สองและควรจะต่ำกว่าความสูงของกล่อง 50px ดูสมเหตุสมผลเช่นกัน; ดูเหมือนว่าไม่น่าเป็นไปได้ที่คุณมักจะต้องการให้องค์ประกอบยุบตัวลงซึ่งสูงไม่ถึง 50 พิกเซลในตอนแรก

อย่างที่คุณเห็นในอนิเมชั่นการเปลี่ยนแปลงที่เกิดขึ้นนั้นเกิดขึ้นอย่างต่อเนื่อง แต่มันก็ไม่สามารถเปลี่ยนแปลงได้ในขณะนี้เมื่อความสูงขั้นต่ำเท่ากับความสูงเต็มที่ปรับโดยขอบด้านล่างจะมีการเปลี่ยนแปลงความเร็วอย่างกะทันหัน นี่เป็นสิ่งที่เห็นได้ชัดเจนในภาพเคลื่อนไหวเพราะมันใช้ฟังก์ชั่นการจับเวลาเชิงเส้นสำหรับการเปลี่ยนทั้งสองและเนื่องจากการเปลี่ยนแปลงทั้งหมดช้ามาก ในกรณีที่เกิดขึ้นจริง (การสาธิตของฉันที่ด้านบน) การเปลี่ยนภาพใช้เวลาเพียง 300ms และการเปลี่ยนแปลงระยะขอบด้านล่างไม่ใช่เชิงเส้น ฉันได้เล่นกับฟังก์ชั่นจับเวลาที่แตกต่างกันมากมายสำหรับการเปลี่ยนทั้งสองและสิ่งที่ฉันจบลงด้วยความรู้สึกว่าพวกเขาทำงานได้ดีที่สุดสำหรับกรณีที่หลากหลาย

ยังคงมีสองปัญหาที่ต้องแก้ไข:

  1. จุดจากด้านบนที่ซึ่งกล่องที่มีความสูงมากกว่า 2000 พิกเซลไม่ได้ถูกซ่อนอย่างสมบูรณ์ในสถานะที่ยุบ
  2. และปัญหาย้อนกลับซึ่งในกรณีที่ไม่ได้ซ่อนกล่องความสูงน้อยกว่า 50 พิกเซลจะสูงเกินไปแม้ว่าการเปลี่ยนแปลงจะไม่ทำงานเพราะความสูงขั้นต่ำทำให้พวกเขาอยู่ที่ 50 พิกเซล

เราแก้ปัญหาแรกด้วยการให้องค์ประกอบคอนเทนเนอร์ a max-height: 0ในกรณียุบด้วยการ0s 0.3sเปลี่ยน ซึ่งหมายความว่าไม่ใช่การเปลี่ยนแปลงจริง ๆ แต่เป็นการเปลี่ยนแปลงที่max-heightมีความล่าช้า มันจะใช้เฉพาะเมื่อการเปลี่ยนแปลงมากกว่า เพื่อให้ทำงานได้อย่างถูกต้องเราต้องเลือกตัวเลขmax-heightสำหรับสถานะตรงกันข้ามสถานะไม่ยุบ แต่แตกต่างจากในกรณี 2000px ซึ่งการเลือกจำนวนมากเกินไปมีผลต่อคุณภาพของการเปลี่ยนแปลงในกรณีนี้มันไม่สำคัญ ดังนั้นเราสามารถเลือกตัวเลขที่สูงมากจนเรารู้ว่าจะไม่มีความสูงใกล้เคียงนี้ ฉันเลือกล้านพิกเซล หากคุณรู้สึกว่าคุณอาจต้องรองรับเนื้อหาที่มีความสูงมากกว่าล้านพิกเซลดังนั้น 1) ฉันขอโทษและ 2) เพียงเพิ่มศูนย์สองสามแห่ง

ปัญหาที่สองคือสาเหตุที่เราไม่ได้ใช้จริงmin-heightสำหรับการเปลี่ยนความสูงขั้นต่ำ แต่จะมี::afterองค์ประกอบหลอกในภาชนะheightที่เปลี่ยนจาก 50px เป็นศูนย์ สิ่งนี้มีผลเช่นเดียวกับmin-height: มันจะไม่ปล่อยให้ภาชนะบรรจุลดลงต่ำกว่าความสูงที่องค์ประกอบหลอกมีอยู่ในปัจจุบัน แต่เนื่องจากเราใช้heightไม่min-heightสามารถใช้max-height(ล่าช้าอีกครั้ง) เพื่อตั้งค่าความสูงจริงขององค์ประกอบหลอกให้เป็นศูนย์เมื่อการเปลี่ยนผ่านสิ้นสุดลงเพื่อให้มั่นใจว่าอย่างน้อยนอกช่วงเปลี่ยนผ่านแม้องค์ประกอบขนาดเล็กจะมี ความสูงที่ถูกต้อง เพราะmin-heightเป็นที่แข็งแกร่งกว่าmax-heightนี้จะไม่ทำงานถ้าเราใช้ภาชนะที่เป็นmin-heightแทนขององค์ประกอบหลอกheight. เช่นเดียวกับmax-heightในย่อหน้าก่อนหน้านี้max-heightยังต้องการค่าสำหรับปลายอีกด้านของการเปลี่ยนแปลง แต่ในกรณีนี้เราสามารถเลือก 50px ได้

ทดสอบใน Chrome (Win, Mac, Android, iOS), Firefox (Win, Mac, Android), Edge, IE11 (ยกเว้นปัญหาการจัดวางเฟล็กบ็อกซ์พร้อมการสาธิตของฉันที่ฉันไม่ได้ทำการดีบัก) และ Safari (Mac, iOS ) เมื่อพูดถึง flexbox ควรจะสามารถทำงานได้โดยไม่ต้องใช้ flexbox ใด ๆ ในความเป็นจริงฉันคิดว่าคุณสามารถทำให้เกือบทุกอย่างทำงานใน IE7 - ยกเว้นความจริงที่ว่าคุณจะไม่มีการเปลี่ยน CSS ทำให้เป็นการออกกำลังกายที่ไม่มีจุดหมาย


35
ฉันหวังว่าคุณจะสั้นลง (ลดความซับซ้อน) โซลูชันของคุณหรือตัวอย่างรหัสอย่างน้อย - ดูเหมือนว่า 90% ของตัวอย่างรหัสไม่เกี่ยวข้องกับคำตอบของคุณ
Gil Epshtain

มีวิธีที่จะทำให้ช่วงการเปลี่ยนภาพเหล่านี้ยังทำงานได้หรือไม่ถ้าตำแหน่งcollapsible-wrapperนั้นมีตำแหน่งที่แน่นอน overflow: hiddenบนแม่เป็นสิ่งจำเป็นสำหรับการเปลี่ยนแปลง แต่รบกวนกับองค์ประกอบตำแหน่งอย่างแน่นอน
pmkro

1
@ pmkro ใช่ฉันมีปัญหาเช่นกัน ฉันแก้ไขมันโดยใช้clip-path: polygon(...)แทนที่จะเป็นoverflow: hiddenเพราะคุณไม่สามารถเปลี่ยนอดีตได้ เป็นทางเลือกสำหรับเบราว์เซอร์รุ่นเก่าฉันใช้การแปลงมาตราส่วนเพิ่มเติม ดูความคิดเห็นที่ด้านบนของgithub.com/StackExchange/Stacks/blob/develop/lib/css/components/…
balpha

2
ดี มันใช้งานได้ดีจริงๆ ควรเป็นคำตอบที่ยอมรับ
เฮนรี่อิงซิมมอนส์

84

คุณสามารถทำได้โดยใช้ jiggery-pokery เล็กน้อย วิธีการตามปกติของฉันคือทำให้เคลื่อนไหวความสูงของ 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
เนื่องจากสิ่งนี้ต้องอาศัยจาวาสคริปต์คุณจึงสามารถเพิ่มการวัดวาอารามได้โดยใช้จาวาสคริปต์ด้วยเช่นกัน!
Quickredfox

18
คุณสามารถทำได้โดยไม่ต้องหุ้ม Just: function growDiv () {var growDiv = document.getElementById ('grow'); if (growDiv.clientHeight) {growDiv.style.height = 0; } else {growDiv.style.height = growDiv.scrollHeight + 'px'; }}
user1742529

8
ลองดู ... พูดคุยเกี่ยวกับคำตอบง่ายๆjsfiddle.net/n5XfG/2596 ... คำตอบของคุณซับซ้อนอย่างเมามันโดยไม่มีเหตุผลดี ไม่ต้องการmax-height, ไม่จำเป็นauto, และโดยเฉพาะอย่างยิ่งไม่จำเป็นสำหรับ Javascript !! เพียงสองประกาศง่ายๆ
VIDesignz

12
@VIDesignz คุณเคลื่อนไหวเกินอัตรากำไร: 100% นี่คือความกว้าง 100% ขององค์ประกอบไม่ใช่ส่วนสูง! ซึ่งหมายความว่าหากคุณมีองค์ประกอบที่มีความสูงมากกว่าความกว้างของมันสิ่งนี้จะไม่ซ่อนมัน นอกจากนี้ที่เกิดขึ้นจริงความเร็วในการเคลื่อนไหวจะแตกต่างกว่าที่กำหนดไว้
Timo Türschmann

3
ฉันตื่นเต้นกับคำตอบของ VIDesignz จนกว่าฉันจะอ่านเพิ่มเติมเกี่ยวกับความคิดเห็นของ Timo ใช่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/ (riffed off jsFiddle ข้างบนของ stephband)


3
ฉันคิดว่านี่เป็นคำตอบที่ดีที่สุด เทคนิคนี้สามารถขยายเพื่อปรับการขยายบนเด็กได้เช่นกัน ในกรณีของฉันฉันสามารถรวมกับช่วงการเปลี่ยนภาพความสูงที่ชัดเจนในเนื้อหาบางส่วนที่ถูกเปิดเผยและผลรวมนั้นประสบความสำเร็จมากกว่าการทำงานสูงสุดรอบความสูงซึ่งดีสำหรับการเปิดเผย แต่แนะนำช่วงเวลาที่น่าอึดอัดใจของ หน่วงเวลาในการซ่อน ไม่ช้าฉันก็จะไม่เคลื่อนไหวเลยนอกจากจะมีการหน่วงเวลาที่ไม่มีความหมายซึ่งทำให้แอปของฉันดูไม่ตอบสนอง ฉันประหลาดใจที่มีคนจำนวนมากดูเหมือนว่าจะยอมรับ
เซมิโคลอน

17
ยกเว้นที่นี่คุณจะไม่เคลื่อนไหวความสูงเลย คุณกำลังเคลื่อนไหว padding ... มันสามารถหายไปได้ดีเพราะมันสามารถเคลื่อนไหวจากสถานะปัจจุบันลงไปที่ 0 แต่ถ้าคุณดูอย่างใกล้ชิดเมื่อมันขยายมันปรากฏขึ้นเปิดด้วยข้อความและจากนั้น padding เท่านั้นที่เคลื่อนไหว ... เพราะมันไม่ ไม่รู้วิธีการเคลื่อนไหวจาก 0 ถึงอัตโนมัติ .... มันต้องการช่วงตัวเลข ... นั่นคือวิธีการทวีต
Rob R

นี่เป็นวิธีแก้ปัญหาที่ดีที่ไม่ได้แฮ็ก มันไม่ใช่คำตอบที่ดีที่สุดสำหรับคำถามนี้แต่มันเป็นทางเลือกที่เหมาะกับฉัน บางครั้งคุณก็ต้องผลของบางภาพเคลื่อนไหวความสูงไม่ได้เป็นภาพเคลื่อนไหวเต็ม :)
อีวานกล้า

วิธีนี้ยังล้มเหลวเมื่อใช้ความล่าช้าในการเปลี่ยน
Michel Joanisse

ฉันยังเห็นด้วยว่าวิธีนี้เป็นวิธีแก้ปัญหาที่สะอาดซึ่งให้การเปลี่ยนถ่ายค่อนข้างลื่นหากภาพเคลื่อนไหวของคุณเร็วพอ (ในกรณีของฉันสำหรับการประสานกับช่วงการเปลี่ยนภาพ 0.1s มันสมบูรณ์แบบ!) มันจะไม่ใช้งานแอพพลิเคชั่นมากมาย แต่ผู้ใช้คนอื่น ๆ จะไม่ถามคำถามนี้!
Remi D

46

วิธีแก้ปัญหาของฉันคือการเปลี่ยนความสูงสูงสุดเป็นความสูงเนื้อหาที่แน่นอนสำหรับภาพเคลื่อนไหวที่ราบรื่นดีจากนั้นใช้ callback 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 แทน
อดัม

3
ก็ใช่ แต่ทำไมคุณถึงใช้ "การเปลี่ยน CSS3 แทน" ถ้าคุณเป็นตัวอย่างในการใช้ jQuery ไลบรารีที่มีโค้ด "เขียนน้อยลงให้ทำมากขึ้น" อยู่แล้ว? ฉันต้องการชี้ให้เห็นว่าเวอร์ชันของคุณอาจดูดีขึ้นมากแม้ว่าจะซับซ้อนกว่านี้หากไม่ได้ใช้ jQuery ดังนั้นจึงสามารถทำงานบนเว็บไซต์ใดก็ได้ ฉันเดาว่าฉันพูดผิดไปมาก ขอโทษด้วยนะ ;)
Kiruse

27
@ Derija93 อาจเป็นเพราะการเปลี่ยน CSS3 มี (ตามแหล่งที่มาทั้งหมดที่ฉันสามารถหาได้) ประสิทธิภาพที่ดีกว่าภาพเคลื่อนไหว jQuery (อันที่จริงสำคัญอย่างมากสำหรับกรณีการใช้งานปัจจุบันของฉันซึ่งนำฉันมาที่นี่)
Mark Amery

4
@ Derija93 'สาเหตุที่ทำให้ภาพเคลื่อนไหว Javascript ทำงานช้าลงเมื่อเทียบกับการเปลี่ยน CSS3 bro และด้วยภาพเคลื่อนไหว jQuery คุณต้องกังวลเกี่ยวกับลูปการเคลื่อนไหว สร้างภาพเคลื่อนไหวเมื่อคลิกจากนั้นคลิกอย่างรวดเร็วและดูในขณะที่ภาพเคลื่อนไหวทำซ้ำตัวเอง สิ่งนี้ถูกจัดการด้วย CSS3
AlbertEngelB

2
@ Dropped.on.Caprica นี่เก่าไปหน่อยแล้ว ฉันบอกไปแล้วว่าฉันเข้าใจผิดแนวคิดที่เขาพยายามแสดงให้เห็น อย่างไรก็ตามสำหรับอนิเมชั่นที่เรียบง่ายแล้ว.stopก็ใช้กลอุบายสำหรับปัญหาลูปแอนิเมชันที่ค่อนข้างซับซ้อน ตอนนี้เมื่อคุณเคลื่อนไหวความสูงและสี แต่ต้องการขัดจังหวะการเคลื่อนไหวความสูงเท่านั้นสิ่งต่าง ๆ กลายเป็นเล่ห์เหลี่ยมเล็กน้อย ... ฉันเข้าใจแล้ว
Kiruse

43

คำตอบที่ได้รับการยอมรับนั้นใช้ได้ดีกับกรณีส่วนใหญ่ แต่มันก็ใช้งานไม่ได้เมื่อคุณdivสามารถปรับความสูงได้อย่างมาก - ความเร็วของภาพเคลื่อนไหวนั้นไม่ได้ขึ้นอยู่กับความสูงของเนื้อหาที่แท้จริง

คุณยังสามารถดำเนินการเคลื่อนไหวที่เกิดขึ้นจริงกับ CSS แต่คุณจำเป็นต้องใช้ JavaScript autoในการคำนวณความสูงของรายการแทนการพยายามที่จะใช้ ไม่จำเป็นต้องใช้ jQuery ถึงแม้ว่าคุณอาจต้องแก้ไขบิตนี้หากคุณต้องการความเข้ากันได้ (ใช้งานได้ใน Chrome รุ่นล่าสุด :)

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 ใด ๆ (ตัวอย่างเช่นจากdocument.getElementById('mydiv')หรือ$('#mydiv').get()) และฟังก์ชันสลับระหว่างการซ่อน / แสดง หากคุณตั้งค่าการเปลี่ยน CSS องค์ประกอบจะทำให้เคลื่อนไหวโดยอัตโนมัติ
Oleg Vaskevich

ฉันเพิ่มตัวอย่าง สิ่งนี้มีความได้เปรียบในการทำงานได้ดีสำหรับเนื้อหาที่มีขนาดแบบไดนามิก
Oleg Vaskevich

3
-1 เนื่องจากไม่ใช่ "ใช้ CSS" ประเด็นของคำถามมีไว้สำหรับโซลูชัน JS-free ผมคิดว่าคำตอบที่ "ถูกต้อง" ที่ไม่สับจะเป็นแบบนี้ แต่ ...
dudewad

16
Downvote สำหรับการใช้ 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
คุณไม่พบคำตอบอื่น ๆ ที่นี่เนื่องจากการโต้ตอบกับ DOM โดยใช้Element.scrollHeightคุณสมบัติต้องใช้ JavaScript และเนื่องจากคำถามระบุไว้ชัดเจนพวกเขาต้องการทำสิ่งนี้โดยไม่ใช้ JavaScript
TylerH

3
มีส่วนอื่น ๆ อีกมากมายของ CSS นอกเหนือจากคลาสหลอกทั้งสองที่สามารถแก้ปัญหานี้ได้เนื่องจากคำตอบที่ได้รับการโหวตสูงสุดในหน้า 1 แสดง การตั้งค่าสไตล์ใน JavaScript ไม่ใช่ "pure 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: ฟังก์ชั่นจับเวลา)
Julian 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>


ทำได้ดีมาก - นี่เป็นวิธีแก้ไขปัญหาที่ไม่ควรมีอยู่จริง การเคลื่อนไหวความสูงสูงสุดคือ bas เว้นแต่ว่าการเปลี่ยนแปลงถูกตั้งค่าเป็น "เชิงเส้น" มันก็แย่มากสำหรับการสร้างเนื้อหา CMS ที่ความสูงเป็นตัวแปร
M_Willett

นี่เป็นสิ่งที่ฉลาด แต่ฉันไม่อยากทำซ้ำองค์ประกอบและเนื้อหา DOM สำหรับสิ่งนี้
Andre Figueiredo

คุณสามารถทำได้โดยไม่ต้องมีคอนเทนเนอร์และมีประสิทธิภาพมากขึ้นโดยการสร้างภาพเคลื่อนไหวtransform: scaleY(1)เนื่องจากการเปลี่ยนแปลงนี้จะไม่ลบพื้นที่ออก
Fabian von Ellerts

21

เมื่อฉันโพสต์สิ่งนี้มีคำตอบมากกว่า 30 คำ แต่ฉันรู้สึกว่าคำตอบของฉันดีขึ้นเมื่อตอบโดยเจค

ฉันไม่พอใจกับปัญหาที่เกิดขึ้นจากการใช้เพียงแค่max-heightและการเปลี่ยน CSS3 เนื่องจากมีผู้แสดงความคิดเห็นหลายคนตั้งข้อสังเกตคุณต้องตั้งค่าของคุณmax-heightให้ใกล้เคียงกับความสูงจริงหรือคุณอาจล่าช้า ดูJSFiddleนี้สำหรับตัวอย่างของปัญหานั้น

เพื่อหลีกเลี่ยงปัญหานี้ (ในขณะที่ยังไม่มี JavaScript) ฉันได้เพิ่มองค์ประกอบ HTML อื่นที่เปลี่ยนtransform: translateYค่า CSS

ซึ่งหมายความว่าทั้งสองmax-heightและtranslateYถูกใช้: 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กว่าscaleเพราะผมไม่ชอบวิธีการที่scaleให้ผลการบีบอัดที่
Andrew Messier

ขอบคุณ @ andrew-messier ฉันลบความคิดเห็นเนื่องจากมีข้อผิดพลาดแปลYไม่ได้ทำงานในcodepen.io/davidtaubmann/pen/zKZvGP (เพราะไม่มีเด็กที่ต้องทำการย้ายจำเป็นต้องแก้ไข) ... แต่ในนี้ หนึ่งที่เราได้อย่างสมบูรณ์แบบสามารถดูเปรียบเทียบจากเฉพาะ MAX-HEIGHT และผสมกับโย (ตามที่ระบุไว้ในคำตอบอื่น ๆ ): codepen.io/davidtaubmann/pen/jrdPER ทั้งหมดนี้ช่วยฉันได้มากกับวิธีการเป้าหมายที่ฉันใช้
DavidTaubmann

18

ตกลงดังนั้นฉันคิดว่าฉันได้คำตอบที่ง่ายที่สุด ... ไม่max-heightใช้การrelativeวางตำแหน่งทำงานกับliองค์ประกอบและเป็น CSS ที่บริสุทธิ์ ฉันยังไม่ได้ทดสอบอะไรเลยนอกจาก Firefox แม้ว่าจะตัดสินจาก CSS มันควรจะใช้ได้กับทุกเบราว์เซอร์

FIDDLE: 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
สิ่งนี้จะทำงานจนกว่าความสูงขององค์ประกอบจะเกินความกว้าง เป็นพื้นฐานของการคำนวณระยะขอบโดยใช้เปอร์เซ็นต์: คำนวณจากความกว้างขององค์ประกอบ ดังนั้นหากคุณมีองค์ประกอบกว้าง 1,000 พิกเซลดังนั้นองค์ประกอบที่ 1100 พิกเซลจะใหญ่เกินไปสำหรับวิธีนี้ในการทำงานหมายความว่าคุณต้องเพิ่มระยะขอบบนสุดนั้น โดยทั่วไปมันเป็นปัญหาเดียวกับการใช้ความสูงหรือความสูงสูงสุด
dudewad

15

แก้ไข: เลื่อนลงสำหรับคำตอบที่ปรับปรุง
ฉันทำรายการแบบหล่นลงและเห็นโพสต์นี้ ... คำตอบที่แตกต่างกัน แต่ฉันตัดสินใจที่จะแบ่งปันรายการแบบหล่นลงของฉันด้วย ... มันไม่สมบูรณ์ แต่อย่างน้อยมันจะใช้ css เพียงอย่างเดียวสำหรับ หล่นลง! ฉันใช้การแปลง: translateY (y) เพื่อแปลงรายการเป็นมุมมอง ...
คุณสามารถดูเพิ่มเติมในการทดสอบ
http://jsfiddle.net/BVEpc/4/
ฉันวาง div ข้างหลังทุก li เพราะฉัน ลิสต์แบบดรอปดาวน์มาจากด้านบนและเพื่อแสดงอย่างถูกต้องสิ่งนี้คือรหัส 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 ใช้ต้นแบบนี้จริง ๆ ! เมนูแบบเลื่อนลงนี้มีไว้สำหรับเมนูย่อยเดียวเท่านั้นและนั่นคือทั้งหมด !! ฉันได้อัปเดตดีกว่าที่สามารถมีเมนูย่อยสองรายการสำหรับทั้งทิศทาง ltr และ rtl พร้อมการรองรับ IE 8
ซอสำหรับ 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
Misha Reyzlin

5
ปัญหาเกิดขึ้นกับกฎการเปลี่ยนแปลงของคุณ เพื่อให้มันทำงานคุณต้องใช้การเปลี่ยนเป็นขั้นต่ำและความสูงสูงสุดด้วย ช่วงการเปลี่ยนภาพ: ความสูง. 5s เชิงเส้น, ความสูงต่ำสุด. 5s เชิงเส้น, ความสูงสูงสุด. 5s เชิงเส้น
Stuart Badminton

2
นี่คือสิ่งที่ฉันได้มาในภายหลังอย่างที่คุณพูดต้องทำให้เคลื่อนไหวได้สูงสุด: jsfiddle.net/gryzzly/n5XfG/3
Misha Reyzlin

11
แน่นอนมีปัญหากับสิ่งนี้ เวลาที่ใช้ในการทำภาพเคลื่อนไหวความสูงสูงสุดไม่ใช่เวลาที่ใช้ในการเปลี่ยนเป็นความสูงอัตโนมัติของกล่อง: ถึงความสูง: อัตโนมัติก่อนก่อนที่ความสูงสูงสุดจะเสร็จสิ้นการสร้างภาพเคลื่อนไหว ในทำนองเดียวกันเมื่อเปลี่ยนเป็น 0 การเปลี่ยนแปลงจะไม่เริ่มต้นทันทีเนื่องจากความสูงสูงสุดเริ่มต้นที่ความสูงมากกว่าความสูง: อัตโนมัติ การเปลี่ยนเป็นความสูงสูงสุด: 1,000px ทำให้สิ่งนี้ชัดเจน: jsfiddle.net/n5XfG/11
stephband

คุณถูกต้องจากการทดสอบเพิ่มเติมฉันสังเกตเห็นสิ่งนี้ ฉันไม่รู้ว่าเต็มความสูง: 0 ถึงความสูง: อัตโนมัติจะถูกนำมาใช้ แต่การใช้ความสูงสูงสุดในบางสถานการณ์สามารถแก้ไขสถานการณ์ที่เป็นไปไม่ได้โดยใช้ CSS เพียงอย่างเดียว
Stuart Badminton

10

โซลูชัน Flexbox

ข้อดี:

  • ง่าย
  • ไม่มี JS
  • การเปลี่ยนแปลงที่ราบรื่น

จุดด้อย:

  • องค์ประกอบจะต้องใส่ในคอนเทนเนอร์ยืดหยุ่นสูงคงที่

วิธีการทำงานคือการมี flex-based อยู่เสมอ: อัตโนมัติในองค์ประกอบที่มีเนื้อหาและการเปลี่ยน flex-grow และ flex-shrink แทน

แก้ไข: JS Fiddle ที่ได้รับแรงบันดาลใจจากอินเทอร์เฟซ Xbox One

* {
  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 Fiddle


7

การขยายคำตอบของ @ jake การเปลี่ยนแปลงจะดำเนินไปจนถึงค่าความสูงสูงสุดทำให้เกิดภาพเคลื่อนไหวที่รวดเร็วมาก - หากคุณตั้งค่าการเปลี่ยนสำหรับทั้ง: โฮเวอร์และปิดคุณสามารถควบคุมความเร็วบ้าได้อีกเล็กน้อย

ดังนั้น li: โฮเวอร์คือเมื่อเมาส์เข้าสู่สถานะแล้วการเปลี่ยนแปลงในคุณสมบัติที่ไม่ได้โฮเวอร์จะเป็นการออกจากเมาส์

หวังว่านี่จะช่วยได้บ้าง

เช่น:

.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) สิ่งนี้ขึ้นอยู่กับการเปลี่ยนแปลง 2s เมื่อเปิดแล้วโค้ดด้านบนเพื่อกลับไปที่สถานะเริ่มต้น ขอบคุณ ... สิ่งนี้ช่วยฉันได้ดีกว่าทั้งหมดที่กล่าวมา +1 ฉันใช้เว็บไซต์นี้เพื่อสร้าง bezier matthewlein.com/ceaser
gcoulby

ตกลงใช้เวลาเพิ่มขึ้นเล็กน้อย การเปลี่ยนแปลง: ทั้งหมด 500ms ลูกบาศก์เบซิเยร์ (0.000, 1.390, 0.000, 0.635) ฉันควรระบุการเปลี่ยนแปลงของฉันไปจาก 5% -100% (แต่ในความเป็นจริงมูลค่าสิ้นสุดประมาณ 28%) ดังนั้นมันขึ้นอยู่กับโครงการ
gcoulby

อย่างแน่นอนมันไม่เหมาะ แต่เป็นการแก้ไขอย่างรวดเร็วหากคุณรู้ว่ารอบความสูงเฉลี่ยจะเป็นอย่างไร
jamie

7

ฉันคิดว่าฉันคิดวิธีแก้ปัญหาที่มั่นคงจริงๆ

ตกลง! ฉันรู้ว่าปัญหานี้เป็นเช่นเดิมเป็นอินเทอร์เน็ต แต่ผมคิดว่าผมมีวิธีการแก้ปัญหาที่ฉันกลายเป็นที่ปลั๊กอินที่เรียกว่ากลายพันธุ์การเปลี่ยน โซลูชันของฉันตั้งค่าstyle=""แอตทริบิวต์สำหรับองค์ประกอบที่ติดตามทุกครั้งที่มีการเปลี่ยนแปลงใน DOM ผลลัพธ์ที่ได้คือคุณสามารถใช้ CSS ที่ดีสำหรับการเปลี่ยนและไม่ใช้การแก้ไขแฮ็กหรือจาวาสคริปต์พิเศษ data-mutant-attributes="X"สิ่งเดียวที่คุณต้องทำคือชุดสิ่งที่คุณต้องการในการติดตามในองค์ประกอบในคำถามโดยใช้

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

แค่นั้นแหละ! วิธีนี้ใช้MutationObserverเพื่อติดตามการเปลี่ยนแปลงใน DOM ด้วยเหตุนี้คุณไม่จำเป็นต้องตั้งค่าใด ๆ หรือใช้จาวาสคริปต์เพื่อสร้างภาพเคลื่อนไหวด้วยตนเอง การเปลี่ยนแปลงจะถูกติดตามโดยอัตโนมัติ อย่างไรก็ตามเนื่องจากใช้ MutationObserver สิ่งนี้จะเปลี่ยนเฉพาะใน IE11 +

ไวโอลิน!


12
โดยปกติเมื่อมีคนถามว่าจะทำอะไร "โดยไม่มี JavaScript" หมายความว่าวิธีแก้ปัญหาจะต้องทำงานบนเบราว์เซอร์ที่ปิดใช้งาน JavaScript มันไม่ได้หมายความว่า "โดยไม่ต้องเขียนสคริปต์ของตัวเอง" ดังนั้นการบอกว่าปลั๊กอินของคุณสามารถใช้งานได้โดยไม่ต้องใช้ JavaScript จะทำให้เข้าใจผิดได้ดีที่สุด - พิจารณาว่าเป็นปลั๊กอิน JavaScript
BoltClock

ฉันควรชี้แจงเมื่อฉันบอกว่าคุณไม่ต้องใช้จาวาสคริปต์พิเศษใด ๆ ฉันหมายความว่าคุณไม่จำเป็นต้องเขียนจาวาสคริปต์ เพียงรวมไลบรารี JS และระบุแอตทริบิวต์ที่คุณต้องการดูใน HTML คุณไม่ต้องใช้ความสูงคงที่หรือคิดอะไรออกไป เพียงแค่มีสไตล์และไป
JonTroncoso

"(... ) คุณไม่จำเป็นต้องตั้งค่าอะไรหรือใช้จาวาสคริปต์เพื่อสร้างภาพเคลื่อนไหวด้วยตนเอง (... )"ดังนั้นคุณจึงใช้ JavaScript เพื่อความสนุก
Roko C. Buljan

6

ต่อไปนี้เป็นวิธีการเปลี่ยนจากความสูงเริ่มต้นใด ๆ รวมถึง 0 เป็นอัตโนมัติ (ขนาดเต็มและยืดหยุ่น) โดยไม่ต้องใช้รหัสที่กำหนดค่ายากสำหรับแต่ละโหนดหรือรหัสผู้ใช้ใด ๆ เพื่อเริ่มต้น: https://github.com/csuwildcat / นี้เป็นพื้นจอกศักดิ์สิทธิ์สำหรับสิ่งที่คุณต้องการผมเชื่อว่า -> 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);

/ * รหัสสำหรับ DEMO * /

    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

1
@ KarolisRamanauskas ไม่นั่นไม่ใช่ปัญหา - IE รองรับทั้ง CSS Keyframes และ requestAnimationFrame ฉันใช้clipเป็นทริกเกอร์คุณสมบัติหุ่นของฉันและด้วยเหตุผลบางอย่าง IE หยุดให้คลิปเคลื่อนไหวได้ ฉันเปลี่ยนความทึบแสงและมันทำงานทั้งหมดอีกครั้ง: codepen.io/csuwldcat/pen/FpzGa ฉันได้อัปเดตรหัสในคำตอบที่ตรงกัน
csuwldcat

1
@csuwldcat วิธีแก้ปัญหาที่ดีมากฉันสังเกตเห็นว่าเนื้อหาปรากฏขึ้นและหายไปเพียงเล็กน้อยเศษส่วนเหตุใดจึงเป็นเช่นนี้ หลีกเลี่ยงได้ไหม
Beto Aveiga

12
ฉันต้องการถอนการลงคะแนนนี้ แต่แทนที่จะตอบคำถามเกี่ยวกับวิธีการทำให้ใช้งานได้คุณแชร์ปลั๊กอินที่คุณเขียนเพื่อให้ใช้งานได้ พวกเราที่อยากรู้อยากเห็นถูกปล่อยให้ทำวิศวกรรมปลั๊กอินของคุณซึ่งไม่สนุกเท่าไหร่ ฉันหวังว่าคุณจะอัปเดตคำตอบของคุณเพื่อให้มีคำอธิบายเพิ่มเติมว่าปลั๊กอินของคุณทำอะไรและทำไม เปลี่ยนรหัสเพื่ออธิบายเพิ่มเติม ตัวอย่างเช่นคุณมีทั้งส่วนของรหัสที่เพิ่งเขียน 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';

คุณควรทิ้ง Javascript นี้ทันทีหลังจากแท็กปิดของ target_box ในแท็กสคริปต์แบบอินไลน์


document.getElementById ('target_box'). getBoundingClientRect (). height ควรจะทำได้ดีที่สุด
แก้ไข

5

ฉันสามารถทำสิ่งนี้ได้ ฉันมี.child& .parentdiv 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 */
}

คุณจะระบุheightบน.parentในpx, หรือปล่อยให้เป็น% autodiv นี้จะปิดบัง.childdiv เมื่อเลื่อนลง


ตัวอย่างการทำงานของสิ่งนี้จะได้รับการชื่นชมอย่างมาก
Neurotransmitter

5

ฉันโพสต์คำตอบด้วย JavaScript และได้รับการ downvoted ดังนั้นได้รำคาญและลองอีกครั้งและแตกด้วย CSS เท่านั้น!

โซลูชันนี้ใช้ 'เทคนิค' สองสามอย่าง:

  • padding-bottom:100%'แฮ็ค' ที่กำหนดเปอร์เซ็นต์ในแง่ของความกว้างปัจจุบันขององค์ประกอบ ข้อมูลเพิ่มเติมเกี่ยวกับเทคนิคนี้
  • การหดห่อด้วยโฟลว์ (จำเป็นต้องมีแผนกเสริมเพื่อทำการแฮ็กสำนักหักบัญชี)
  • การใช้https://caniuse.com/#feat=css-writing-mode ที่ไม่น่าตื่นเต้นและการเปลี่ยนแปลงบางอย่างเพื่อเลิกทำ (ทำให้สามารถใช้การแฮ็ก padding ด้านบนในบริบทแนวตั้ง)

แม้ว่าผลที่สุดคือเราได้รับการเปลี่ยนการแสดงโดยใช้ CSS เท่านั้นและฟังก์ชั่นการเปลี่ยนแปลงเดียวเพื่อให้เกิดการเปลี่ยนแปลงอย่างราบรื่น จอกศักดิ์สิทธิ์!

แน่นอนว่ามีข้อเสีย! ฉันไม่สามารถหาวิธีควบคุมความกว้างที่เนื้อหาถูกตัด ( overflow:hidden); เนื่องจากการแฮ็ก padding-bottom ความกว้างและความสูงมีความสัมพันธ์อย่างใกล้ชิด อาจมีวิธีแม้ว่าดังนั้นจะกลับมา

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>


ข้อเสียอื่น ๆ ของสิ่งนี้คือคุณไม่สามารถย้ายเคอร์เซอร์ออกจาก "hoverme" div ไปยังรายการของรายการเพื่อโต้ตอบกับพวกเขา (เห็นได้ชัดว่าเหตุผลในการถาม OP) ดังนั้นจึงเป็นประโยชน์เพียงฟังก์ชั่นเคล็ดลับเครื่องมือมากกว่า พูดเมนูที่มีเมนูย่อยซ้อนกัน
TylerH

นั่นเป็นผลสืบเนื่องมาจากวิธีการตั้งคำถามและไม่เกี่ยวข้องกับเทคนิค คุณสามารถเปลี่ยนทริกเกอร์ให้เป็นinput[type="checkbox"]:checkedแทนที่:hoverหากคุณต้องการ (เช่นคุณไม่ต้องการใช้จาวาสคริปต์เพื่อเพิ่มคลาส)
EoghanM

ฉันหมายถึงไม่ว่าคำถามจะถูกกำหนดอย่างไรหากการดำเนินการตามแนวทางของโซลูชั่นมี จำกัด ดังนั้นจึงควรกล่าวถึงในคำตอบของโซลูชันนั้น (หรือคิดเป็นพิเศษ ) คุณพูดถึงวิธีแก้ปัญหานี้คือ 'โฮลี่เกรล' แต่ผู้ที่ผ่านการเปลี่ยนแปลงไม่สามารถที่จะโฉบเฉี่ยว ... ดูเหมือนจะไม่เป็นทางออกที่ดีที่สุดสำหรับฉัน
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-heightในliองค์ประกอบมากกว่าการห่อulองค์ประกอบมากกว่าการตัด

เหตุผลก็คือความล่าช้าของขนาดเล็กmax-heightsนั้นน้อยกว่าที่เห็นได้ชัดเจน (ถ้าเลย) เมื่อเทียบกับขนาดใหญ่max-heightsและฉันยังสามารถตั้งค่าของฉันmax-heightเทียบกับfont-sizeของจำนวนliมากกว่าจำนวนมากโดยใช้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;
}

สิ่งนี้จะช่วยให้คุณมี div ที่ตอนแรกแสดงเนื้อหาที่มีความสูงสูงสุด 200px และเมื่อวางเมาส์เหนือขนาดก็จะสูงอย่างน้อยเท่าเนื้อหาทั้งหมดของ div Div ไม่กลายเป็น 3000px แต่ 3000px เป็นขีด จำกัด ที่ฉันใช้ ตรวจสอบให้แน่ใจว่ามีการเปลี่ยนแปลงที่ไม่ใช่: โฮเวอร์มิฉะนั้นคุณอาจได้รับการเรนเดอร์แปลก ๆ ด้วยวิธีนี้การโฮเวอร์สืบทอดจาก non: hover

การเปลี่ยนไม่ทำงานในรูปแบบ px เป็น% หรือเป็นอัตโนมัติ คุณต้องใช้หน่วยการวัดเดียวกัน มันใช้งานได้ดีสำหรับฉัน การใช้ HTML5 ทำให้มันสมบูรณ์แบบ ....

จำไว้ว่ามีการแก้ไขอยู่เสมอ ... ; )

หวังว่าใครบางคนพบว่ามีประโยชน์นี้


3

โซลูชันความสูงสูงสุดจาก Jake ใช้งานได้ดีหากค่าความสูงสูงสุดที่กำหนดไว้ไม่สูงกว่าความสูงจริง (เพราะมิฉะนั้นจะมีความล่าช้าและปัญหาเวลาที่ไม่พึงประสงค์) ในทางกลับกันหากค่าฮาร์ดโค้ดโดยบังเอิญไม่สูงกว่าความสูงจริงองค์ประกอบจะไม่เปิดขึ้นอย่างสมบูรณ์

โซลูชัน CSS ต่อไปนี้เท่านั้นยังต้องใช้ขนาดฮาร์ดโค้ดที่ควรใหญ่กว่าขนาดจริงส่วนใหญ่ที่เกิดขึ้น อย่างไรก็ตามวิธีนี้ยังใช้งานได้หากขนาดจริงอยู่ในบางสถานการณ์ที่ใหญ่กว่าขนาดตายตัว ในกรณีดังกล่าวการเปลี่ยนแปลงอาจกระโดดได้เล็กน้อย แต่จะไม่ทิ้งองค์ประกอบที่มองเห็นได้บางส่วนไว้ ดังนั้นวิธีนี้สามารถใช้กับเนื้อหาที่ไม่รู้จักเช่นจากฐานข้อมูลที่คุณเพิ่งรู้ว่าเนื้อหานั้นมักจะไม่ใหญ่กว่า x พิกเซล แต่มีข้อยกเว้น

แนวคิดคือการใช้ค่าลบสำหรับ margin-bottom (หรือ margin-top สำหรับแอนิเมชันที่ต่างกันเล็กน้อย) และวางองค์ประกอบเนื้อหาลงในองค์ประกอบกลางที่มี overflow: hidden ระยะขอบติดลบขององค์ประกอบเนื้อหาจึงลดความสูงขององค์ประกอบกลาง

รหัสต่อไปนี้ใช้การเปลี่ยนแปลงบนขอบล่างจาก -150px ถึง 0px ใช้งานได้เพียงอย่างเดียวตราบใดที่องค์ประกอบเนื้อหาไม่สูงกว่า 150px นอกจากนี้ยังใช้การเปลี่ยนผ่านสำหรับความสูงสูงสุดสำหรับองค์ประกอบกลางจาก 0px ถึง 100% ในที่สุดสิ่งนี้จะซ่อนองค์ประกอบกลางหากองค์ประกอบเนื้อหาสูงกว่า 150px สำหรับความสูงสูงสุดการเปลี่ยนแปลงนั้นใช้เพื่อหน่วงเวลาแอปพลิเคชั่นภายในหนึ่งวินาทีเมื่อปิดไม่ใช่สำหรับเอฟเฟกต์ visiual ที่ราบรื่น (และดังนั้นจึงสามารถเรียกใช้จาก 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>

ค่าสำหรับส่วนล่างของขอบควรเป็นค่าลบและใกล้เคียงกับความสูงจริงขององค์ประกอบเนื้อหา หากค่าของ absoute มีขนาดใหญ่กว่าจะมีปัญหาความล่าช้าและระยะเวลาที่คล้ายกันเช่นเดียวกับวิธีแก้ปัญหาความสูงสูงสุดซึ่งอาจ จำกัด ได้ตราบใดที่ขนาดของรหัสฮาร์ดไม่ใหญ่กว่าของจริง หากค่าสัมบูรณ์สำหรับส่วนต่างกำไรต่ำกว่าความสูงจริงค่า 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 และเปลี่ยนที่แทนที่จะเป็นความสูงหรือความสูงสูงสุดหรือขนาด Y () ฯลฯ ด้วยความเร็วที่รวดเร็วพอที่จะทำให้ความสูงเปลี่ยนเป็นสิ่งที่คุณต้องการ ในการแปลงความสูงจริงด้วย CSS เป็นอัตโนมัติไม่สามารถทำได้ในขณะนี้ แต่การแปลงเนื้อหาภายในคือการเปลี่ยนขนาดตัวอักษร

  • หมายเหตุ - มี javascript ใน codepen แต่มีวัตถุประสงค์เพียงเพื่อเพิ่ม / ลบคลาส css เมื่อคลิกสำหรับหีบเพลง สิ่งนี้สามารถทำได้ด้วยปุ่มตัวเลือกที่ซ่อนอยู่ แต่ฉันไม่ได้มุ่งเน้นไปที่การเปลี่ยนแปลงความสูง

1
ทำซ้ำคำตอบนี้อย่างมีประสิทธิภาพแต่ไม่ใช้เอฟเฟกต์ความทึบจาง
SeldomNeedy

ตกลง แนวทางที่ดีกว่า
Mike S.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.