การเปลี่ยนผ่านคุณสมบัติการแสดงผล CSS


1446

ขณะนี้ฉันกำลังออกแบบเมนู CSS 'mega dropdown' - โดยทั่วไปแล้วเป็นเมนูแบบเลื่อนลง CSS-only ทั่วไป แต่เมนูที่มีเนื้อหาประเภทต่างๆ

ในขณะนี้ดูเหมือนว่าการเปลี่ยน CSS 3 จะไม่ใช้กับคุณสมบัติ 'display'นั่นคือคุณไม่สามารถทำการเปลี่ยนแปลงใด ๆ จากdisplay: noneเป็นdisplay: block(หรือชุดค่าผสม)

มีวิธีใดบ้างสำหรับเมนูระดับสองจากตัวอย่างด้านบนเพื่อ 'จางหายไป' เมื่อมีคนอยู่เหนือรายการเมนูระดับบนสุดหรือไม่

ฉันทราบว่าคุณสามารถใช้ช่วงการเปลี่ยนภาพได้visibility:แต่ฉันไม่สามารถคิดวิธีการใช้งานได้อย่างมีประสิทธิภาพ

ฉันได้ลองใช้ความสูง แต่ก็ล้มเหลวอย่างน่าสังเวช

ฉันก็ทราบด้วยว่ามันเป็นเรื่องเล็กน้อยที่จะบรรลุเป้าหมายนี้โดยใช้ JavaScript แต่ฉันต้องการท้าทายตัวเองให้ใช้ CSS เพียงอย่างเดียวและฉันคิดว่าฉันกำลังจะมาถึงในระยะสั้น ๆ


การเปลี่ยนแปลง CSS ทำงานได้หรือไม่ถ้าคุณใช้กับคุณสมบัติความทึบแทนที่จะแสดง
Paul D. Waite

13
ตำแหน่ง: สัมบูรณ์; ทัศนวิสัย: ซ่อนอยู่; เหมือนกับ display: none;
Jawad

8
@Jawad: เฉพาะถ้าคุณเพิ่มสิ่งที่ต้องการz-index:0ได้เป็นอย่างดี
DanMan

7
@Jawad: ไม่แนะนำให้ใช้visibility: hiddenจนกว่าคุณจะต้องการให้โปรแกรมอ่านหน้าจออ่าน (ในขณะที่เบราว์เซอร์ทั่วไปไม่รองรับ) มันกำหนดเฉพาะการมองเห็นขององค์ประกอบ (เช่นพูดopacity: 0) และก็ยังคงสามารถเลือกได้คลิกได้และสิ่งที่มันเคยเป็น; มันมองไม่เห็น
Forest Katsch

1
ไม่รองรับpointer-eventsใน IE 8,9,10 ดังนั้นจึงไม่เป็นไรเสมอไป
Steven Pribilinskiy

คำตอบ:


1351

คุณสามารถเชื่อมโยงช่วงการเปลี่ยนภาพสองช่วงขึ้นไปและvisibilityเป็นสิ่งที่มีประโยชน์ในครั้งนี้

div {
  border: 1px solid #eee;
}
div > ul {
  visibility: hidden;
  opacity: 0;
  transition: visibility 0s, opacity 0.5s linear;
}
div:hover > ul {
  visibility: visible;
  opacity: 1;
}
<div>
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
  </ul>
</div>

(อย่าลืมคำนำหน้าผู้ขายไปที่ transitionสถานที่ให้บริการ)

รายละเอียดเพิ่มเติมในบทความนี้


10
คำตอบนี้ดูเหมือนจะทำงานน้อยกว่าคำตอบอื่น ๆ และบรรลุสิ่งที่เราคาดหวังจากการแสดง: ไม่มี / บล็อก; ขอบคุณ ช่วยฉันทีหนึ่งครั้ง
เบรนแดน

21
ใช่ปัญหาของสิ่งนี้คือสิ่งที่อยู่ข้างหลังมันจะทับซ้อนแม้ว่าจะมองไม่เห็นก็ตาม ผมพบว่าการใช้ความสูง: 0 ทางออกที่ดีมาก
จอช bedo

739
นี่เป็นสิ่งที่ดี แต่ปัญหาคือองค์ประกอบ "การมองเห็นที่ซ่อนอยู่" ยังคงใช้พื้นที่ในขณะที่ "ไม่มีการแสดง" ไม่ได้
Rui Marques

41
ฉันอาจจะพลาดบางสิ่งบางอย่าง แต่ทำไมคุณถึงเปลี่ยนแปลงทัศนวิสัยและความทึบ? จะไม่ตั้งค่าความทึบเป็น 0 ซ่อนองค์ประกอบ - ทำไมคุณต้องตั้งค่าการเปิดเผยเป็นซ่อนเร้นด้วย?
GMA

21
@GeorgeMillo หากคุณตั้งค่าเฉพาะความทึบองค์ประกอบยังคงอยู่ในการแสดงผลหน้าเว็บ (คุณไม่สามารถคลิกที่คิดเช่น)
adriendenat

800

คุณต้องซ่อนองค์ประกอบด้วยวิธีการอื่นเพื่อให้สามารถใช้งานได้

ฉันทำเอฟเฟ็กต์สำเร็จโดยการวางตำแหน่งทั้งสอง<div>อย่างและตั้งค่าที่ซ่อนไว้ให้opacity: 0เป็น

หากคุณสลับdisplayคุณสมบัติจากnoneเป็นblockเปลี่ยนของคุณในองค์ประกอบอื่น ๆ จะไม่เกิดขึ้น

ในการหลีกเลี่ยงปัญหานี้ให้อนุญาตให้องค์ประกอบเป็นdisplay: blockแต่ซ่อนองค์ประกอบโดยปรับวิธีการใด ๆ ต่อไปนี้:

  1. ตั้งค่าการheight0
  2. ตั้งค่าการopacity0
  3. overflow: hiddenตำแหน่งนอกองค์ประกอบของกรอบขององค์ประกอบที่มีอีก

มีโซลูชั่นที่มีแนวโน้มมากขึ้น display: noneแต่คุณไม่สามารถดำเนินการเปลี่ยนแปลงถ้าคุณสลับองค์ประกอบที่จะ ตัวอย่างเช่นคุณอาจลองทำสิ่งนี้:

div {
    display: none;
    transition: opacity 1s ease-out;
    opacity: 0;
}
div.active {
    opacity: 1;
    display: block;
}

แต่นั่นจะไม่ทำงาน จากประสบการณ์ของฉันฉันพบสิ่งนี้ไม่ทำอะไรเลย

ด้วยเหตุนี้คุณจะต้องรักษาองค์ประกอบไว้เสมอdisplay: block- แต่คุณสามารถทำได้โดยทำสิ่งนี้:

div {
    transition: opacity 1s ease-out;
    opacity: 0;
    height: 0;
    overflow: hidden;
}
div.active {
    opacity: 1;
    height: auto;
}

29
ขอบคุณ Jim สำหรับคำตอบอย่างละเอียด คุณพูดถูกเกี่ยวกับความจริงที่ว่าถ้าการแสดงผล: การเปลี่ยนแปลงคุณสมบัติทั้งหมดการเปลี่ยนแปลงทั้งหมดของคุณจะไม่ทำงาน ซึ่งเป็นความอัปยศ - ฉันสงสัยว่าเหตุผลที่อยู่เบื้องหลังคืออะไร ในหมายเหตุด้านบนลิงก์เดียวกับที่ฉันโพสต์ในคำถามเดิมคุณสามารถดูได้ว่าฉันอยู่ที่ไหน ปัญหาเดียว (เล็ก) ที่ฉันมีอยู่ใน Chrome [5.0.375.125] เมื่อเพจโหลดคุณสามารถดูเมนูได้อย่างรวดเร็วจางหายไปเนื่องจากองค์ประกอบถูกโหลดบนหน้าเว็บ Firefox 4.0b2 และ Safari 5.0 นั้นดีจริง ๆ ... บั๊กหรือบางอย่างที่ฉันพลาดไป?
RichardTape

7
ฉันยอมรับว่าสิ่งนี้ถูกต้องและจะสนับสนุนสิ่งนี้ หัวขึ้นสำหรับนักเดินทางในอนาคต ฉันพบโซลูชันที่ใช้งานได้ใน Chrome แต่ฉันพบว่าล้มเหลวใน iPhone 4: visibility:hidden; opacity:0; -webkit-transition: all .2s ease-in-out;ไม่เพียง แต่การเปลี่ยนแปลงนี้ไม่ถูกต้อง แต่องค์ประกอบเป้าหมายจะไม่ปรากฏขึ้น QA จะล้มเหลวคุณฉันและแม่ของคุณ
SimplGy

1
คุณสามารถเปลี่ยนคุณสมบัติการมองเห็นได้เช่นกัน .. เพียงแค่บอกว่า
Cu7l4ss

2
หากคุณตั้งค่าสถานะที่ซ่อนอยู่เป็นheight: 0;และไม่เปลี่ยนสถานะการเปลี่ยนจะไม่ทำงาน ฉันลองทำสิ่งนี้แค่พยายามเปลี่ยนความทึบ ฉันต้องลบheight: 0;
chovy

10
คุณเพิ่งชนะการโหวตเพราะoverflow: hiddenขอบคุณมาก!
thiagoh

277

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

ตัวอย่างรหัส (คุณสามารถนำไปใช้กับเมนูของคุณได้) การสาธิต :

เพิ่ม CSS ต่อไปนี้ในสไตล์ชีทของคุณ:

@-webkit-keyframes fadeIn {
    from { opacity: 0; }
      to { opacity: 1; }
}
@keyframes fadeIn {
    from { opacity: 0; }
      to { opacity: 1; }
}

จากนั้นนำfadeInภาพเคลื่อนไหวไปใช้กับเด็กเมื่อผู้ปกครองวางตัวชี้ (และชุดของหลักสูตรdisplay: block):

.parent:hover .child {
    display: block;
    -webkit-animation: fadeIn 1s;
    animation: fadeIn 1s;
}

อัปเดต 2019 - วิธีที่รองรับการเฟดออก:

(จำเป็นต้องใช้รหัส JavaScript บางตัว)

// We need to keep track of faded in elements so we can apply fade out later in CSS
document.addEventListener('animationstart', function (e) {
  if (e.animationName === 'fade-in') {
      e.target.classList.add('did-fade-in');
  }
});

document.addEventListener('animationend', function (e) {
  if (e.animationName === 'fade-out') {
      e.target.classList.remove('did-fade-in');
   }
});
div {
    border: 5px solid;
    padding: 10px;
}

div:hover {
    border-color: red;
}

.parent .child {
  display: none;
}

.parent:hover .child {
  display: block;
  animation: fade-in 1s;
}

.parent:not(:hover) .child.did-fade-in {
  display: block;
  animation: fade-out 1s;
}

@keyframes fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes fade-out {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}
<div class="parent">
    Parent
    <div class="child">
        Child
    </div>
</div>


3
ขอบคุณสำหรับสิ่งนี้. height: 0เคล็ดลับ (สำหรับเปลี่ยน) ดังกล่าวข้างต้นดูเหมือนจะไม่ทำงานเพราะความสูงที่ได้รับการตั้งค่าเป็น 0 ในจางจากการเปลี่ยนแปลง แต่เคล็ดลับนี้ดูเหมือนว่าจะทำงานได้ดี
Elliot Winkler

41
ขอบคุณมีประโยชน์มาก แต่จะจางมันออกไปได้อย่างไร
Illiou

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

7
คำตอบที่ดีที่สุดเป็นไปไม่ได้ที่จะมีการเปลี่ยนผ่าน แต่ใช่ด้วยภาพเคลื่อนไหว
มิเคล

6
แล้วอนิเมชั่นย้อนกลับเป็นอย่างไรเมื่อองค์ประกอบควรจะค่อยๆหายไปอย่างช้าๆ?
สีเขียว

77

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

display: none;และvisibility: hidden;เป็นสองสิ่งที่แตกต่างอย่างสิ้นเชิง
ทั้งสองจะมีผลทำให้องค์ประกอบที่มองไม่เห็น แต่visibility: hidden;ก็ยังคงแสดงผลในรูปแบบ แต่ก็ไม่เห็นได้ชัดดังนั้น
องค์ประกอบที่ซ่อนอยู่ยังคงใช้พื้นที่และยังคงแสดงผลแบบอินไลน์หรือเป็นบล็อกหรือบล็อกแบบอินไลน์หรือตารางหรือสิ่งที่displayองค์ประกอบบอกให้แสดงเป็นและใช้พื้นที่ตาม
องค์ประกอบอื่น ๆ จะไม่ย้ายโดยอัตโนมัติเพื่อใช้พื้นที่นั้น องค์ประกอบที่ซ่อนไม่แสดงพิกเซลที่แท้จริงไปยังเอาต์พุต

display: noneบนมืออื่น ๆ จริงจะช่วยป้องกันองค์ประกอบจากการแสดงผลทั้งหมด
มันไม่ใช้พื้นที่รูปแบบใด ๆ
องค์ประกอบอื่น ๆ ที่จะครอบครองพื้นที่บางส่วนหรือทั้งหมดที่ใช้โดยองค์ประกอบนี้จะปรับให้เข้ากับพื้นที่นั้นราวกับว่าองค์ประกอบนั้นไม่มีอยู่เลย

display ไม่ได้เป็นเพียงคุณลักษณะทางภาพอื่น
มันกำหนดโหมดการแสดงผลทั้งหมดขององค์ประกอบเช่นไม่ว่าจะเป็นblock, inline, inline-block, table, table-row, table-cell, list-itemหรืออะไรก็ตาม!
แต่ละคนมีโครงร่างแตกต่างกันมากและจะไม่มีวิธีที่สมเหตุสมผลในการเคลื่อนไหวหรือการเปลี่ยนแปลงอย่างราบรื่น (ลองจินตนาการถึงการเปลี่ยนจากหรือblockไปสู่inlineในทางกลับกันอย่างราบรื่น!)

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


8
สิ่งที่ดีดังที่กล่าวไว้ข้างต้นอาจเป็นเรื่องที่น่ายินดีอย่างยิ่งที่ได้รับคำอธิบายที่สมเหตุสมผลว่าทำไมการเปลี่ยนภาพไม่ใช้กับคุณลักษณะการแสดงผล
kqr

8
ฉันไม่เห็นด้วย. มันทำให้รู้สึกสมบูรณ์ ถ้า display: none to display: block เกิดขึ้นทันทีในช่วงเริ่มต้นของการเปลี่ยนแปลงนั่นจะยอดเยี่ยม และสำหรับการเปลี่ยนกลับหากมันไปจาก display: block to display: ไม่มีเลยเมื่อสิ้นสุดการเปลี่ยนแปลงนั่นจะสมบูรณ์แบบ
เคอร์ติส Yallop

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

2
Tryniko: display: none ไม่มีการเปลี่ยนแปลงขนาดขององค์ประกอบเป็นสี่เหลี่ยมจัตุรัสขนาด 0x0 - มันจะลบมันออกจาก DOM คุณสามารถเคลื่อนไหวจากสี่เหลี่ยมไปยังจุดหนึ่งโดยทำให้คุณสมบัติความกว้างและความสูงเป็นศูนย์จากนั้นองค์ประกอบอื่น ๆ จะไหลไปรอบ ๆ ราวกับว่ามันมี 'display: none' แต่แอตทริบิวต์ 'display' จะยังคงเป็น 'block'; องค์ประกอบยังอยู่ใน DOM แนวคิดของการสร้างภาพเคลื่อนไหวระหว่างจอแสดงผล: บล็อกและจอแสดงผล: ไม่มีสิ่งใดไร้สาระ: ไม่มีสถานะระดับกลาง องค์ประกอบมีอยู่ใน DOM หรือไม่ก็ตามไม่ว่าเล็กหรือมองไม่เห็น
Steve Thorpe

1
มันไม่ได้ไร้สาระที่จะเคลื่อนไหวคุณสมบัติไม่ต่อเนื่องเคลื่อนไหว คุณสมบัติแบบแยกเช่นdisplayไม่สามารถเปลี่ยนได้อย่างราบรื่นเหมือนคุณสมบัติอื่น ๆ แต่นั่นไม่ได้หมายความว่าเวลาไม่สำคัญ ความสามารถในการควบคุมเมื่อการเปลี่ยนจากdisply:blockเป็นdisplay:noneเกิดขึ้นเป็นสิ่งสำคัญมาก เช่นเดียวกับ @CurtisYallop อธิบาย ถ้าผมต้องการที่จะเปลี่ยนแปลงจากopacity:1ไปopacity:0และแล้วการเปลี่ยนแปลงdisplay:blockที่จะdisplay:noneฉันควรจะสามารถที่จะทำมัน
Jens

55

แทนที่จะเรียกกลับมาซึ่งไม่มีอยู่ใน CSS เราสามารถใช้transition-delayคุณสมบัติ

#selector {
    overflow: hidden; // Hide the element content, while height = 0
    height: 0; opacity: 0;
    transition: height 0ms 400ms, opacity 400ms 0ms;
}
#selector.visible {
    height: auto; opacity: 1;
    transition: height 0ms 0ms, opacity 600ms 0ms;
}

แล้วเกิดอะไรขึ้นที่นี่?

  1. เมื่อvisibleมีการเพิ่มคลาสทั้งคู่heightและopacityเริ่มการเคลื่อนไหวโดยไม่ชักช้า (0 ms)heightจะใช้เวลา 0 มิลลิวินาทีในการทำให้แอนิเมชั่นสมบูรณ์ (เทียบเท่าdisplay: block) และopacityใช้เวลา 600 ms

  2. เมื่อvisibleลบคลาสออกแล้วopacityเริ่มภาพเคลื่อนไหว (ความล่าช้า 0 ms, ระยะเวลา 400 ms) และความสูงรอ 400 ms และจากนั้นทันทีเท่านั้น (0 ms) คืนค่าเริ่มต้น (เทียบเท่าdisplay: noneกับการโทรกลับภาพเคลื่อนไหว)

visibilityหมายเหตุวิธีนี้จะดีกว่าคนที่ใช้ ในกรณีเช่นนี้องค์ประกอบยังคงใช้พื้นที่บนหน้าและไม่เหมาะสมเสมอไป

สำหรับตัวอย่างเพิ่มเติมโปรดดูที่บทความนี้


8
ประหลาดใจที่นี่ไม่มี upvotes เพิ่มเติม - โซลูชันที่ชาญฉลาดนี้ทำงานได้อย่างสมบูรณ์แบบ
ประโคม

3
ใช้งานได้เฉพาะกับheight:100%ที่สามารถทำลายเค้าโครงในบางกรณี วิธีแก้ปัญหาที่ยอดเยี่ยมหากนั่นไม่ใช่ปัญหา หนึ่งในไม่กี่คนที่ทำงานแบบสองทิศทาง
Fabian von Ellerts

มันเยี่ยมมาก! ฉันสามารถทำให้มันง่ายขึ้นได้อีกในกรณีของฉันเพราะฉันต้องการให้เวลาอนิเมชั่นจางหายไปเหมือนกับเวลาที่จางหาย แทนที่จะใช้ฉันเพียงแค่ใช้transition: height 0ms 0ms, opacity 600ms 0ms transition-delay: 0s
Jacob Lockard

52

display ไม่ใช่หนึ่งในคุณสมบัติที่การเปลี่ยนผ่านทำงานได้

ดูคุณสมบัติ CSS ที่เคลื่อนไหวได้สำหรับรายการของคุณสมบัติ CSS ที่สามารถมีการเปลี่ยนแปลงที่นำไปใช้กับพวกเขาได้ ดูค่า CSS และหน่วยโมดูลระดับ 4 การรวมค่า: การแก้ไขการบวกและการสะสมสำหรับวิธีการแก้ไข

มากถึง CSS 3 แสดงอยู่ใน9.1 คุณสมบัติจาก CSS (เพียงปิดป๊อปอัพคำเตือน)

ฉันได้ลองใช้ความสูง แต่ก็ล้มเหลวอย่างน่าสังเวช

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


ลิงค์ไม่ได้ชี้โดยตรงไปที่ส่วนคุณสมบัติที่เคลื่อนไหวได้อีกต่อไป
Andrew Lam

1
@AndrewLam แก้ไขแล้ว ขอบคุณ
robocat

34

คุณสามารถเพิ่มภาพเคลื่อนไหวที่กำหนดเองในคุณสมบัติบล็อกได้ทันที

@keyframes showNav {
  from {opacity: 0;}
  to {opacity: 1;}
}
.subnav-is-opened .main-nav__secondary-nav {
  display: block;
  animation: showNav 250ms ease-in-out both;
}

การสาธิต

ในการสาธิตนี้การเปลี่ยนแปลงเมนูย่อยจากdisplay:noneเป็นdisplay:blockและยังจัดการเพื่อจางหายไป


ควรmyfirstจะอยู่showNavที่นี่ แล้ว Firefox ล่ะ น่าเสียดายที่ฉันไม่พบสิ่งที่เกี่ยวข้องในหน้าตัวอย่างที่คุณพูดถึง
Sebastian vom Meer

ขอบคุณ @SebastianG ฉันได้ทำการแก้ไขและเพิ่มข้อมูลเพิ่มเติมด้านบนแล้ว
Manish Pradhan

@Sebastian vom Meer: Firefox รุ่นเก่าต้องใช้คำนำหน้าผู้ขาย "-moz-" ดูรหัสที่แก้ไข
Herr_Schwabullek

23
เว้นแต่ฉันจะทำบางสิ่งบางอย่างลิงก์ "สาธิต" จะไม่แสดงการเปลี่ยนเมนูย่อยอีกต่อไป
สมจริง

1
การเปลี่ยนแปลงที่ถูกต้องสำหรับสิ่งที่ไม่มีที่ว่าง (เช่นกรณีที่มีจอแสดงผล: ไม่มี) กับสิ่งที่ใช้พื้นที่ (display: block) เป็นการขยายมิติไม่ใช่จางหายไป หากมันเป็นเรื่องของการมองเห็นที่ซ่อนอยู่ (ซึ่งใช้พื้นที่ แต่ไม่สามารถมองเห็นได้) ให้มองเห็นได้ขนาดก็ยังคงเดิมและจางหายไปนั้นเหมาะสม คำตอบเหล่านี้ไม่สามารถแก้ปัญหาได้
Triynko

21

ตามW3C Working Draft 19 พฤศจิกายน 2556 displayไม่ใช่คุณสมบัติที่สามารถเคลื่อนไหวได้ โชคดีที่visibilityสามารถเคลื่อนไหวได้ คุณสามารถโยงการเปลี่ยนแปลงด้วยการเปลี่ยนความทึบ ( JSFiddle ):

  • HTML:

    <a href="http://example.com" id="foo">Foo</a>
    <button id="hide-button">Hide</button>
    <button id="show-button">Show</button>
  • CSS:

    #foo {
        transition-property: visibility, opacity;
        transition-duration: 0s, 1s;
    }
    
    #foo.hidden {
        opacity: 0;
        visibility: hidden;
        transition-property: opacity, visibility;
        transition-duration: 1s, 0s;
        transition-delay: 0s, 1s;
    }
  • JavaScript สำหรับการทดสอบ:

    var foo = document.getElementById('foo');
    
    document.getElementById('hide-button').onclick = function () {
        foo.className = 'hidden';
    };
    
    document.getElementById('show-button').onclick = function () {
        foo.className = '';
    };

โปรดทราบว่าหากคุณเพียงแค่ทำให้ลิงค์นั้นโปร่งใสโดยไม่ต้องตั้งค่าลิงก์visibility: hiddenนั้นจะยังคงสามารถคลิกได้


1
ฉันไม่เห็นการเปลี่ยนแปลงใด ๆ เลยในตัวอย่าง jsfiddle
Gino

@Gino ฉันคงได้โดยการเปลี่ยนไป0 0sเห็นได้ชัดว่าในอดีตเบราว์เซอร์ที่ฉันใช้สำหรับการทดสอบไม่มีหน่วยเป็นศูนย์ อย่างไรก็ตามครั้งไม่มีหน่วยเป็นไม่ได้เป็นส่วนหนึ่งของคำแนะนำ W3C สมัคร 29 กันยายน 2016
feklee

สิ่งนี้ควรได้รับการสนับสนุนเพิ่มเติม ฉันพบว่ามันเป็นหนึ่งในโซลูชั่นที่ดีที่สุด
Arthur Tarasov

การใช้การหน่วงเวลาเป็นเพียงตรรกะที่ดีที่สุดในการทำความเข้าใจวิธีการทำงานของ เคลื่อนไหวและซ่อน เลิกซ่อนและทำให้เคลื่อนไหว โซลูชั่นที่สมบูรณ์แบบสำหรับฉัน
Bruno Pitteli Gonçalves

14

แก้ไข: แสดงไม่มีการใช้ในตัวอย่างนี้

@keyframes hide {
  0% {
    display: block;
    opacity: 1;
  }
  99% {
    display: block;
  }
  100% {
    display: none;
    opacity: 0;
  }
}

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

และสิ่งที่สำคัญที่สุดคือการรักษาเฟรมสุดท้ายไว้หลังจากที่ภาพเคลื่อนไหวสิ้นสุดลงโดยใช้โหมดเติมภาพเคลื่อนไหว: ส่งต่อ

.hide {
   animation: hide 1s linear;
   animation-fill-mode: forwards;
}

นี่คือตัวอย่างสองตัวอย่าง: https://jsfiddle.net/qwnz9tqg/3/


ด้วยวิธีdisplay: noneนี้ไม่ทำงานแล้ว?
Bart Calixto

ควรเป็น 'โหมดเติมนิเมชั่น: ส่งต่อ' ไม่ 'ไปข้างหน้า'
Alex

การแก้ไขจะต้องมีหกตัวอักษรและฉันขอแนะนำให้แก้ไขเท่านั้นดังนั้นความคิดเห็น
Alex

1
@Alex Ok แก้ไข Typo แล้ว สิ่งที่น่าสนใจคือคำตอบของฉันไม่ทำงานตามที่คาดไว้ แต่ก็มีเหตุผลที่จะคิดว่าฉันจะเก็บไว้จนกว่าเบราว์เซอร์จะสนับสนุน
Pawel

3
อย่างที่คุณเห็นในซอนี้กับชุดเคอร์เซอร์display: none, ไม่เคยถูกนำมาใช้จริง ๆ jsfiddle.net/3e6sduqh
robstarbuck

13

เคล็ดลับ JavaScript ที่เรียบร้อยของฉันคือการแยกสถานการณ์ทั้งหมดออกเป็นสองฟังก์ชั่นที่แตกต่างกัน !

ในการจัดเตรียมสิ่งต่าง ๆ จะมีการประกาศตัวแปรส่วนกลางหนึ่งตัวและกำหนดตัวจัดการเหตุการณ์หนึ่งตัว:

  var tTimeout;
  element.addEventListener("transitionend", afterTransition, true);//firefox
  element.addEventListener("webkitTransitionEnd", afterTransition, true);//chrome

จากนั้นเมื่อซ่อนองค์ประกอบฉันใช้สิ่งนี้:

function hide(){
  element.style.opacity = 0;
}

function afterTransition(){
  element.style.display = 'none';
}

สำหรับการดูองค์ประกอบอีกครั้งฉันกำลังทำสิ่งนี้:

function show(){
  element.style.display = 'block';
  tTimeout = setTimeout(timeoutShow, 100);
}

function timeoutShow(){
  element.style.opacity = 1;
}

มันใช้งานได้ดี!


สิ่งนี้ใช้งานได้เนื่องจากการหน่วงเวลาและไม่ใช่เพราะคำสั่ง javascript อยู่ในฟังก์ชันแยกต่างหาก เวลาที่ล่าช้าดูเหมือนจะเป็นวิธีแก้ปัญหาที่ดีในหลายกรณี :)

10

ฉันวิ่งเข้าไปในนี้วันนี้ด้วยposition: fixedคำกริยาที่ฉันนำมาใช้ใหม่ ฉันไม่สามารถรักษามันdisplay: noneแล้วทำให้เคลื่อนไหวได้เพราะมันเพิ่งจะปรากฏขึ้นและz-index (ค่าลบเป็นต้น) ก็ทำสิ่งแปลก ๆ เช่นกัน

ฉันใช้ a height: 0ถึงheight: 100%ด้วย แต่ใช้งานได้ก็ต่อเมื่อคำกริยาปรากฏขึ้น นี่เหมือนกับว่าคุณใช้left: -100%หรืออะไรบางอย่าง

จากนั้นมันทำให้ฉันรู้สึกว่ามีคำตอบง่ายๆ ร้อยละ

ก่อนอื่นคำกริยาที่ซ่อนอยู่ของคุณ สังเกตเห็นheightเป็น0และตรวจสอบheightการประกาศในช่วงการเปลี่ยน ... มันมี500ms, ซึ่งมีความยาวมากกว่าของฉันopacityเปลี่ยนแปลง โปรดจำไว้ว่าสิ่งนี้มีผลต่อการเปลี่ยนสถานะการเฟดออก: ส่งกลับคำกริยากลับสู่สถานะเริ่มต้น

#modal-overlay {
    background: #999;
    background: rgba(33,33,33,.2);
    display: block;
    overflow: hidden;
    height: 0;
    width: 100%;
    position: fixed;
    top: 0;
    left: 0;
    opacity: 0;
    z-index: 1;
    -webkit-transition: height 0s 500ms, opacity 300ms ease-in-out;
       -moz-transition: height 0s 500ms, opacity 300ms ease-in-out;
            -ms-transition: height 0s 500ms, opacity 300ms ease-in-out;
         -o-transition: height 0s 500ms, opacity 300ms ease-in-out;
        transition: height 0s 500ms, opacity 300ms ease-in-out;
}

ประการที่สองคำกริยาที่มองเห็นของคุณ สมมติว่าคุณกำลังตั้งค่าไป.modal-active bodyตอนนี้heightคือ100%และการเปลี่ยนแปลงของฉันก็เปลี่ยนไป ฉันต้องการheightจะมีการเปลี่ยนแปลงได้ทันทีและจะใช้opacity300ms

.modal-active #modal-overlay {
    height: 100%;
    opacity: 1;
    z-index: 90000;
    -webkit-transition: height 0s, opacity 300ms ease-in-out;
       -moz-transition: height 0s, opacity 300ms ease-in-out;
        -ms-transition: height 0s, opacity 300ms ease-in-out;
         -o-transition: height 0s, opacity 300ms ease-in-out;
            transition: height 0s, opacity 300ms ease-in-out;
}

นั่นมันทำงานได้เหมือนมีเสน่ห์


การขึ้นรูปแบบของคุณในการจัดตำแหน่งคุณสมบัตินำหน้าผู้ขาย👍
George Green

9

จากคำตอบบางส่วนและคำแนะนำอื่น ๆ ต่อไปนี้ใช้งานได้ดีสำหรับเมนูแบบโฮเวอร์ (ฉันใช้สิ่งนี้กับBootstrap  3 โดยเฉพาะ):

nav .dropdown-menu {
    display: block;
    overflow: hidden;
    max-height: 0;
    opacity: 0;
    transition: max-height 500ms, opacity 300ms;
    -webkit-transition: max-height 500ms, opacity 300ms;
}
nav .dropdown:hover .dropdown-menu {
    max-height: 500px;
    opacity: 1;
    transition: max-height 0, opacity 300ms;
    -webkit-transition: max-height 0, opacity 300ms;
}

คุณสามารถใช้heightแทนmax-heightถ้าคุณระบุค่าทั้งสองเนื่องจากheight:autoไม่อนุญาตให้ใช้กับtransitions ค่าโฮเวอร์ของmax-heightความต้องการจะมากกว่าheightเมนู


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

8

ฉันพบวิธีที่ดีกว่าสำหรับปัญหานี้คุณสามารถใช้ CSS Animation และสร้างเอฟเฟกต์ที่ยอดเยี่ยมสำหรับการแสดงรายการได้

    .item {
     display: none;
}

.item:hover {
     display: block;
     animation: fade_in_show 0.5s
}

@keyframes fade_in_show {
     0% {
          opacity: 0;
          transform: scale(0)
     }
     100% {
          opacity: 1;
          transform: scale(1)
     }
}

ขอบคุณสำหรับเคล็ดลับที่มีประโยชน์นี้ทำงานได้อย่างสมบูรณ์แบบ
Sedat Kumcu

6

ฉันเคยเจอปัญหานี้หลายครั้งและตอนนี้ก็ไปกับ:

.block {
  opacity: 1;
  transition: opacity 250ms ease;
}

.block--invisible {
  pointer-events: none;
  opacity: 0;
}

โดยการเพิ่มคลาสblock--invisibleองค์ประกอบทั้งหมดจะไม่สามารถคลิกได้ แต่องค์ประกอบทั้งหมดที่อยู่ด้านหลังจะเป็นเพราะpointer-events:noneเบราว์เซอร์หลักทุกตัวรองรับ (ไม่มี IE <11)


คุณช่วยยกตัวอย่างนี้ได้ไหม
GarethAS

1
ใช้งานได้ดี แต่ควรสังเกตว่าตัวชี้เหตุการณ์ไม่ทำงานกับ IE ต่ำกว่า 11
user1702965

เพิ่มบันทึกย่อสำหรับ IE ต่ำกว่า 11
DominikAngerer

หากคุณจำเป็นต้องกล่าวว่าองค์ประกอบด้านบนของทุกอย่าง (เช่นเมนู) นี่เป็นวิธีที่สะอาดที่สุดในการทำเช่นนี้ในปี 2019 การสนับสนุนนั้นมั่นคงสำหรับpointer-events
Josh Davenport

5

เปลี่ยนไปoverflow:hidden overflow:visibleมันทำงานได้ดีขึ้น ฉันใช้สิ่งนี้:

#menu ul li ul {
    background-color:#fe1c1c;
    width:85px;
    height:0px;
    opacity:0;
    box-shadow:1px 3px 10px #000000;
    border-radius:3px;
    z-index:1;
    -webkit-transition:all 0.5s ease;
    -moz-transition:all 0.6s ease;
}

#menu ul li:hover ul  {
    overflow:visible;
    opacity:1;
    height:140px;
}

visibleจะดีกว่าเพราะการกระทำเหมือนกับoverflow:hiddendisplay:none


อันนี้เป็นตั๋วสำหรับฉัน ขอบคุณ!
Dan Loewenherz

5

ไม่จำเป็นต้องใช้ JavaScript และไม่จำเป็นต้องมีขนาดความสูงสูงสุดอย่างมาก แต่การตั้งค่าของคุณmax-heightในองค์ประกอบข้อความของคุณและใช้หน่วยญาติตัวอักษรเช่นหรือrem emด้วยวิธีนี้คุณสามารถตั้งค่าความสูงสูงสุดที่ใหญ่กว่าคอนเทนเนอร์ของคุณในขณะที่หลีกเลี่ยงความล่าช้าหรือ "popping" เมื่อเมนูปิด:

HTML

<nav>
  <input type="checkbox" />
  <ul>
    <li>Link 1</li>
    <li>Link 1</li>
    <li>Link 1</li>
    <li>Link 1</li>
  </ul>
</nav>

CSS

nav input + ul li { // Notice I set max-height on li, not ul
   max-height: 0;
}

nav input:checked + ul li {
   max-height: 3rem; // A little bigger to allow for text-wrapping - but not outrageous
}

ดูตัวอย่างได้ที่นี่: http://codepen.io/mindfullsilence/pen/DtzjE


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

ทำไมคะแนนน้อยมาก นี่เป็นคำตอบที่ดีมากและอาจเป็นคำตอบที่ฉันใช้
mwilcox

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

5

หลังจากเขียนคำตอบที่ได้รับการยอมรับจาก Guillermo แล้ว CSS สเปคการเปลี่ยนผ่านของ 2012-04-03 ได้เปลี่ยนพฤติกรรมของการเปลี่ยนแปลงการมองเห็นและตอนนี้มันเป็นไปได้ที่จะแก้ปัญหานี้ในวิธีที่สั้นลงโดยไม่ต้องใช้การเปลี่ยนแปลงล่าช้า

.myclass > div {
                   transition:visibility 1s, opacity 1s;
                   visibility:hidden;  opacity:0
               }
.myclass:hover > div
               {   visibility:visible; opacity:1 }

เวลาทำงานที่ระบุสำหรับการเปลี่ยนภาพทั้งสองควรจะเหมือนกัน (แม้ว่าเวลาในการมองเห็นจะนานกว่าเล็กน้อยจะไม่เป็นปัญหา)

สำหรับรุ่นที่ทำงานดูโพสต์บล็อกของฉันCSS การเปลี่ยนการมองเห็น

เขียนชื่อของคำถาม"การเปลี่ยนบนจอแสดงผล: คุณสมบัติ"และเพื่อตอบสนองต่อความคิดเห็นจาก Rui Marques และ josh ไปยังคำตอบที่ยอมรับ:

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

มันจะไม่ลบองค์ประกอบทั้งหมดอย่างสมบูรณ์ display:noneเพียงแค่ทำให้มองไม่เห็น แต่ก็ยังคงอยู่ในผังเอกสารและมีผลต่อตำแหน่งขององค์ประกอบต่อไปนี้

การเปลี่ยนที่ลบองค์ประกอบที่คล้ายกันอย่างสมบูรณ์display:noneสามารถทำได้โดยใช้ความสูง (ตามที่ระบุโดยคำตอบและความคิดเห็นอื่น ๆ ) ความสูงสูงสุดหรือระยะขอบบน / ล่าง แต่ดูที่ ฉันจะเปลี่ยนความสูงได้อย่างไร: 0; สูง: อัตโนมัติ; ใช้ CSS หรือไม่ และบล็อกของฉันโพสต์การแก้ไขปัญหาสำหรับการเปลี่ยน CSS ในคุณสมบัติดิสเพลย์และส่วนสูงบนจอแสดงผลและความสูงคุณสมบัติ

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


4

ในที่สุดฉันก็พบทางออกสำหรับฉันด้วยการรวมopacityกับposition absolute(ไม่ต้องใช้พื้นที่เมื่อซ่อน)

.toggle {
  opacity: 0;
  position: absolute;
  transition: opacity 0.8s;
}

.parent:hover .toggle {
  opacity: 1;
  position: static;
}

4

ฉันสงสัยว่าทุกคนที่เพิ่งเริ่มต้นการเปลี่ยน CSS จะค้นพบอย่างรวดเร็วว่าพวกเขาไม่ทำงานหากคุณกำลังแก้ไขคุณสมบัติการแสดงผล (บล็อก / ไม่มี) ในเวลาเดียวกัน วิธีแก้ปัญหาหนึ่งที่ยังไม่ได้กล่าวถึงคือคุณสามารถใช้display:block/noneเพื่อซ่อน / แสดงองค์ประกอบต่อไป แต่ตั้งค่าความทึบของมันเป็น 0 เพื่อให้ได้แม้ว่ามันdisplay:blockจะยังมองไม่เห็นก็ตาม

จากนั้นจะจางหายไปในเพิ่ม CSS คลาสอื่นเช่น "เปิด" ซึ่งตั้งค่าความทึบเป็น 1 และกำหนดการเปลี่ยนแปลงสำหรับความทึบ ดังที่คุณอาจจินตนาการได้คุณจะต้องใช้ JavaScript เพื่อเพิ่มคลาส "on" ในองค์ประกอบ แต่อย่างน้อยคุณก็ยังใช้ CSS สำหรับการเปลี่ยนแปลงจริง

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


ยอดเยี่ยมขอบคุณ! display:noneผมเขียนคำตอบอื่นด้วยตัวอย่างที่ใช้งานได้จริงกับ
mojuba

4

มันง่ายเหมือนดังต่อไปนี้ :)

@keyframes fadeout {
    0% { opacity: 1; height: auto; }
    90% { opacity: 0; height: auto; }
    100% { opacity: 0; height: 0;
}
animation: fadeout linear 0.5s 1 normal forwards !important;

height 0;ได้รับมันจะจางหายไปแล้วทำให้มัน ตรวจสอบให้แน่ใจว่าได้ใช้การส่งต่อเพื่อให้อยู่ในสถานะสุดท้าย


สิ่งนี้จะรีเซ็ตทันทีเมื่อลบคลาสดังนั้นจึงไม่ใช่ความคิดที่ดี
Sean T

2

วิธีนี้มีความเข้ากันได้ดีมากและฉันยังไม่เห็น:

.hidden-element {
  position: absolute;
  z-index: -1;
  pointer-events: none;
  visibility: hidden;
  opacity: 0;
  transition: visibility 0s, opacity .5s ease-out;
}

.hidden-element.visible {
  position: static;
  z-index: auto;
  pointer-events: auto;
  visibility: visible;
  opacity: 1;
}

คำอธิบาย : จะใช้visibility: hiddenเคล็ดลับ (ซึ่งเข้ากันได้กับ“การแสดงและการเคลื่อนไหว” ในขั้นตอนเดียว) แต่จะใช้การรวมกันposition: absolute; z-index: -1; pointer-events: none;เพื่อให้แน่ใจว่าภาชนะที่ซ่อนไม่ใช้พื้นที่และไม่ได้คำตอบที่จะปฏิสัมพันธ์ของผู้ใช้


1
แต่การเปลี่ยนแปลงpositionยังจะทำให้องค์ประกอบกระตุกรอบ ๆ ไม่?
Arsylum

position: absoluteเอาล่ะแน่นอน: หมายความว่าองค์ประกอบไม่ใช้พื้นที่ใด ๆ ตามที่อธิบายไว้ในคำอธิบาย เมื่อสวิตช์ไปposition: staticและปรากฏขึ้นจะใช้พื้นที่เช่นองค์ประกอบปกติซึ่งเป็นจุดของคำถามนี้ ฉันขอแนะนำให้คุณลอง!
Christophe Marois

2
ฉันทำ. แต่ถ้าผมเข้าใจขวาคำถามที่เกี่ยวกับการเปลี่ยน เช่นเดียวกับใน "ภาพเคลื่อนไหวราบรื่น"
Arsylum

2

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

https://jsfiddle.net/b9chris/hweyecu4/17/

เริ่มต้นด้วยกล่องเช่น:

<div id="box" class="hidden">Lorem</div>

กล่องที่ซ่อนอยู่

div.hidden {
    display: none;
}
#box {
    transition: opacity 1s;
}

เราจะใช้เคล็ดลับที่พบใน q / a ที่เกี่ยวข้องตรวจสอบ offsetHeight เพื่อเค้นเบราว์เซอร์ทันที:

https://stackoverflow.com/a/16575811/176877

ขั้นแรกให้ไลบรารีทำเคล็ดลับข้างต้นให้เป็นระเบียบ:

$.fn.noTrnsn = function () {
    return this.each(function (i, tag) {
        tag.style.transition = 'none';
    });
};
$.fn.resumeTrnsn = function () {
    return this.each(function (i, tag) {
        tag.offsetHeight;    
        tag.style.transition = null;
    });
};

ต่อไปเราจะใช้มันเพื่อเปิดเผยกล่องและจางหายไปใน:

$('#button').on('click', function() {
    var tag = $('#box');
    if (tag.hasClass('hidden'))
        tag.noTrnsn().removeClass('hidden')
        .css({ opacity: 0 })
        .resumeTrnsn().css({ opacity: 1 });
    else
        tag.css({ opacity: 0 });
});

จางกล่องนี้เข้าและออก ดังนั้น.noTrnsn()จะปิดการเปลี่ยนแล้วเราเอาhiddenชั้นซึ่งพลิกdisplayจากการเริ่มต้นของnone blockจากนั้นเราตั้งค่าความทึบเป็น 0 เพื่อเตรียมพร้อมสำหรับการซีดจางในตอนนี้เมื่อเราตั้งค่าสเตจ.resumeTrnsn()แล้ว และสุดท้ายเปลี่ยนการตั้งค่าความทึบเป็น 1

หากไม่มีห้องสมุดทั้งการเปลี่ยนแปลงที่จะแสดงและการเปลี่ยนแปลงความทึบจะทำให้เราได้ผลลัพธ์ที่ไม่พึงประสงค์ หากเราเพียงแค่ลบการเรียกห้องสมุดเราจะไม่ได้รับการเปลี่ยนเลย

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

แฟนซี!

https://jsfiddle.net/b9chris/hweyecu4/22/

#box {
    transition: height 1s, opacity 1s;
}

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

$.fn.wait = function (time, fn) {
    if (time)
        this.delay(time);
    if (!fn)
        return this;

    var _this = this;
    return this.queue(function (n) {
        fn.call(_this);
        n();
    });
};

นี่เป็นวิธีการอำนวยความสะดวกที่ให้เรามีส่วนร่วมในคิว fx / แอนิเมชันที่มีอยู่ของ jQuery โดยไม่จำเป็นต้องใช้เฟรมเวิร์กแอนิเมชันใด ๆ ที่ตอนนี้ถูกแยกออกใน jQuery 3.x ฉันจะไม่อธิบายว่า jQuery ทำงานอย่างไร แต่พอเพียงที่จะพูด.queue()และการ.stop()ประปาที่ jQuery ช่วยให้เราสามารถป้องกันไม่ให้แอนิเมชั่นของเราเหยียบกัน

ลองทำเอฟเฟกต์สไลด์ลง

$('#button').on('click', function() {
    var tag = $('#box');
    if (tag.hasClass('hidden')) {
        // Open it
        // Measure it
        tag.stop().noTrnsn().removeClass('hidden').css({
            opacity: 0, height: 'auto'
        });
        var h = tag.height();
        tag.css({ height: 0 }).resumeTrnsn()
        // Animate it
        .css({ opacity: 1, height: h })
        .wait(1000, function() {
            tag.css({ height: 'auto' });
        });
    } else {
        // Close it
        // Measure it
        var h = tag.noTrnsn().height();
        tag.stop().css({ height: h })
        .resumeTrnsn()
        // Animate it
        .css({ opacity: 0, height: 0 })
        .wait(1000, function() {
            tag.addClass('hidden');
        });
    }
});

รหัสนี้เริ่มต้นด้วยการตรวจสอบ#boxและไม่ว่าจะเป็นที่ซ่อนอยู่ในปัจจุบันโดยการตรวจสอบในชั้นเรียน แต่จะประสบความสำเร็จมากขึ้นโดยใช้การwait()เรียกไลบรารี่โดยการเพิ่มhiddenไลบรารี่คลาสที่ส่วนท้ายของแอนิเมชั่น slideout / fade ซึ่งคุณคาดว่าจะพบว่ามันถูกซ่อนอยู่หรือไม่ - ตัวอย่างที่ง่ายกว่าไม่สามารถทำได้ สิ่งนี้เกิดขึ้นเมื่อเปิดใช้งานการแสดง / การซ่อนอิลิเมนต์ซ้ำไปซ้ำมาซึ่งเป็นข้อบกพร่องในตัวอย่างก่อนหน้านี้เนื่องจากคลาสที่ซ่อนไม่เคยถูกเรียกคืน

คุณยังสามารถเห็นการเปลี่ยนแปลง CSS และคลาสที่ถูกเรียกใช้หลังจาก.noTrnsn()ตั้งค่าทั่วไปสำหรับภาพเคลื่อนไหวรวมถึงการวัดเช่นการวัดสิ่งที่จะเป็นความสูงสุดท้าย#boxโดยไม่แสดงให้ผู้ใช้เห็นก่อนการโทร.resumeTrnsn()ออกและสร้างภาพเคลื่อนไหวจากชุดเต็ม สเตจไปยังค่า CSS เป้าหมาย

คำตอบเก่า

https://jsfiddle.net/b9chris/hweyecu4/1/

คุณสามารถเปลี่ยนมันเมื่อคลิกด้วย:

function toggleTransition() {
  var el = $("div.box1");

  if (el.length) {
    el[0].className = "box";
    el.stop().css({maxWidth: 10000}).animate({maxWidth: 10001}, 2000, function() {
        el[0].className = "box hidden";
    });
  } else {
    el = $("div.box");
    el[0].className = "box";
    el.stop().css({maxWidth: 10001}).animate({maxWidth: 10000}, 50, function() {
        el[0].className = "box box1";
    });
  }

  return el;
}

someTag.click(toggleTransition);

CSS คือสิ่งที่คุณคาดเดา:

.hidden {
    display: none;
}
.box {
    width: 100px;
    height: 100px;
    background-color: blue;
    color: yellow;
    font-size: 18px;
    left: 20px;
    top: 20px;
    position: absolute;
    -webkit-transform-origin: 0 50%;
    transform-origin: 0 50%;
    -webkit-transform: scale(.2);
    transform: scale(.2);
    -webkit-transition: transform 2s;
    transition: transform 2s;
}
.box1{
    -webkit-transform: scale(1);
    transform: scale(1);
}

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

หมายเหตุ: ฉันกำลังดูถูกเหยียดหยาม.animate(maxWidth)ที่นี่เพื่อหลีกเลี่ยงsetTimeoutสภาพการแข่งขัน setTimeoutเป็นวิธีที่รวดเร็วในการแนะนำข้อบกพร่องที่ซ่อนอยู่เมื่อคุณหรือคนอื่นหยิบรหัสโดยไม่รู้ตัว สามารถฆ่าได้อย่างง่ายดายด้วย.animate() .stop()ฉันแค่ใช้มันเพื่อทำให้การหน่วงเวลา 50 ms หรือ 2000 ms บนคิว fx มาตรฐานซึ่งง่ายต่อการค้นหา / แก้ไขโดยตัวแปลงสัญญาณอื่น ๆ ที่สร้างขึ้นจากด้านบนนี้


1

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

ปรากฎว่าvisibilityคุณสมบัติ CSS มีค่าcollapseซึ่งโดยทั่วไปจะใช้สำหรับรายการตาราง อย่างไรก็ตามหากใช้กับองค์ประกอบอื่น ๆ มันจะทำให้พวกมันถูกซ่อนไว้อย่างมีประสิทธิภาพเช่นเดียวกับdisplay: hiddenแต่ด้วยความสามารถที่เพิ่มขึ้นซึ่งองค์ประกอบนั้นไม่ใช้พื้นที่ใด ๆ และคุณยังสามารถทำให้องค์ประกอบที่เป็นปัญหาเกิดขึ้น

ด้านล่างเป็นตัวอย่างง่ายๆของการดำเนินการนี้

function toggleVisibility() {
  let exampleElement = document.querySelector('span');
  if (exampleElement.classList.contains('visible')) {
    return;
  }
  exampleElement.innerHTML = 'I will not take up space!';
  exampleElement.classList.toggle('hidden');
  exampleElement.classList.toggle('visible');
  setTimeout(() => {
    exampleElement.classList.toggle('visible');
    exampleElement.classList.toggle('hidden');
  }, 3000);
}
#main {
  display: flex;
  flex-direction: column;
  width: 300px;
  text-align: center;
}

.hidden {
  visibility: collapse;
  opacity: 0;
  transition: visibility 2s, opacity 2s linear;
}

.visible {
  visibility: visible;
  opacity: 1;
  transition: visibility 0.5s, opacity 0.5s linear;
}
<div id="main">
  <button onclick="toggleVisibility()">Click Me!</button>
  <span class="hidden"></span>
  <span>I will get pushed back up...</span>
</div>


1

ทางออกที่ง่ายที่สุดสำหรับปัญหาคืออย่าลังเลที่จะระบุdisplay:noneใน CSS ของคุณอย่างไรก็ตามคุณจะต้องเปลี่ยนเป็นblock(หรืออะไรก็ได้) โดยใช้ JavaScript จากนั้นคุณจะต้องเพิ่มคลาสในองค์ประกอบของคุณด้วยคำถามที่จริงแล้ว ไม่เปลี่ยนแปลงกับ setTimeout () นั่นคือทั้งหมดที่

เช่น:

<style>
    #el {
        display: none;
        opacity: 0;
    }
    #el.auto-fade-in {
        opacity: 1;
        transition: all 1s ease-out; /* Future, future, please come sooner! */
        -webkit-transition: all 1s ease-out;
        -moz-transition: all 1s ease-out;
        -o-transition: all 1s ease-out;
    }
</style>

<div id=el>Well, well, well</div>

<script>
    var el = document.getElementById('el');
    el.style.display = 'block';
    setTimeout(function () { el.className = 'auto-fade-in' }, 0);
</script>

นี่คือการทดสอบในเบราว์เซอร์สติล่าสุด เห็นได้ชัดว่าไม่ควรทำงานใน Internet Explorer 9 หรือเก่ากว่า


1

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

@-webkit-keyframes fadeIn {
    from { opacity: 0; }
      to { opacity: 1; }
}

@-webkit-keyframes fadeOut {
    from { opacity: 1; }
      to { opacity: 0; }
}

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

ตัวอย่างjsFiddle

CSS

@-webkit-keyframes pushDown {
  0% {
    height: 10em;
  }
  25% {
    height: 7.5em;
  }
  50% {
    height: 5em;
  }
  75% {
    height: 2.5em;
  }
  100% {
    height: 0em;
  }
}

.push-down {
    -webkit-animation: pushDown 2s forwards linear;
}

JavaScript

var element = document.getElementById("element");

// Push item down
element.className = element.className + " push-down";

1

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

ลองตัวอย่างด้านล่าง ...

$(document).ready(function() {
  // Assign transition event
  $("table").on("animationend webkitAnimationEnd", ".visibility_switch_off", function(event) {
    // We check if this is the same animation we want
    if (event.originalEvent.animationName == "col_hide_anim") {
      // After the animation we assign this new class that basically hides the elements.
      $(this).addClass("animation-helper-display-none");
    }

  });

  $("button").click(function(event) {

    $("table tr .hide-col").toggleClass(function() {
      // We switch the animation class in a toggle fashion...
      // and we know in that after the animation end, there
      // is will the animation-helper-display-none extra
      // class, that we nee to remove, when we want to
      // show the elements again, depending on the toggle
      // state, so we create a relation between them.
      if ($(this).is(".animation-helper-display-none")) {
        // I'm toggling and there is already the above class, then
        // what we want it to show the elements , so we remove
        // both classes...
        return "visibility_switch_off animation-helper-display-none";
      }
      else {
        // Here we just want to hide the elements, so we just
        // add the animation class, the other will be added
        // later be the animationend event...
        return "visibility_switch_off";
      }
    });
  });
});
table th {
  background-color: grey;
}

table td {
  background-color: white;
  padding: 5px;
}

.animation-helper-display-none {
  display: none;
}

table tr .visibility_switch_off {
  animation-fill-mode: forwards;
  animation-name: col_hide_anim;
  animation-duration: 1s;
}

@-webkit-keyframes col_hide_anim {
  0% {opacity: 1;}
  100% {opacity: 0;}
}

@-moz-keyframes col_hide_anim {
  0% {opacity: 1;}
  100% {opacity: 0;}
}

@-o-keyframes col_hide_anim {
  0% {opacity: 1;}
  100% {opacity: 0;}
}

@keyframes col_hide_anim {
  0%   {opacity: 1;}
  100% {opacity: 0;}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
  <theader>
    <tr>
      <th>Name</th>
      <th class='hide-col'>Age</th>
      <th>Country</th>
    </tr>
  </theader>
  <tbody>
    <tr>
      <td>Name</td>
      <td class='hide-col'>Age</td>
      <td>Country</td>
    </tr>
  </tbody>
</table>

<button>Switch - Hide Age column with fadeout animation and display none after</button>


0

หากคุณใช้ jQuery เพื่อตั้งชั้นเรียนของคุณสิ่งนี้จะได้ผล 100%:

$(document).ready(function() {
  $('button').click(function() {
    var container = $('.container');
    
    if (!container.hasClass('active')) {
      container.addClass('show').outerWidth();
      container.addClass('active');
    }
    else {
      container.removeClass('active').one('transitionend', function() {
        container.removeClass('show');
      });
    }
  });
});
.container {
  display: none;
  opacity: 0;
  transition: opacity 0.3s ease;
}

.container.show {
  display: flex;
}
 
.container.active {
  opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button">Toggle</button>

<div class="container">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>

แน่นอนคุณสามารถใช้ jQuery .fadeIn()และ.fadeOut()ฟังก์ชั่นได้ แต่ข้อดีของการตั้งค่าคลาสแทนคือในกรณีที่คุณต้องการเปลี่ยนเป็นค่าแสดงผลอื่นนอกเหนือจากblock(ตามค่าเริ่มต้นด้วย.fadeIn()และ.fadeOut())

ที่นี่ฉันกำลังเปลี่ยนไปแสดงflexด้วยเอฟเฟกต์จาง ​​ๆ


0

แทนที่จะใช้displayคุณสามารถเก็บองค์ประกอบ 'ปิดหน้าจอ' ได้จนกว่าคุณจะต้องการจากนั้นตั้งค่าตำแหน่งให้เป็นตำแหน่งที่คุณต้องการและเปลี่ยนมันในเวลาเดียวกัน นี่จะทำให้เกิดปัญหาการออกแบบอื่น ๆ ทั้งหมดดังนั้นระยะของคุณอาจแตกต่างกันไป

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


0

คุณสามารถใช้การเปิดเผย CSS : ซ่อน / มองเห็นแทนการแสดงผล : ไม่มี / บล็อก

div {
    visibility:hidden;
    -webkit-transition: opacity 1s ease-out;
    -moz-transition: opacity 1s ease-out;
    -o-transition: opacity 1s ease-out;
    transition: opacity 1s ease-out;
    opacity: 0;
}

parent:hover > div {
    opacity: 1;
    visibility: visible;
}

5
สิ่งนี้สงวนพื้นที่แม้ว่าปล่อยให้หลุมว่างเปล่า หากคุณต้องการยุบช่องว่างคุณจะต้องสร้างความสูงหรือทรัพย์สินอื่น ๆ
Marcy Sutton

0

ผมเริ่มโครงการโครงกระดูกที่เรียกว่ามาเปิดสลับการแสดงผล Animate

ตัวช่วยโครงกระดูกนี้จะช่วยให้คุณเลียนแบบการแสดง / ซ่อน jQuery ได้อย่างง่ายดาย แต่ด้วยภาพเคลื่อนไหวการเปลี่ยนผ่าน CSS 3 เข้า / ออก

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

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

มาร์กอัปส่วนใหญ่สำหรับแนวคิดที่ฉันใช้คือ CSS และมีจาวาสคริปต์น้อยมากที่ใช้จริง

มีตัวอย่างที่นี่: http://marcnewton.co.uk/projects/toggle-display-animate/

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