Overgangen op de CSS-weergave-eigenschap

Ik ben momenteel bezig met het ontwerpen van een CSS ‘mega dropdown’-menu – in feite een gewoon CSS-only dropdown-menu, maar een die verschillende soorten inhoud bevat.

Op dit moment het lijkt erop dat CSS 3-overgangen niet van toepassing zijn op de eigenschap ‘display’, dat wil zeggen dat u geen enkele overgang kunt maken vanuit display: noneom display: block(of een willekeurige combinatie).

Is er een manier om het menu van het tweede niveau uit het bovenstaande voorbeeld te laten ‘infaden’ wanneer iemand de muisaanwijzer op een van de menu-items op het hoogste niveau houdt?

Ik weet dat je overgangen kunt gebruiken voor de eigenschap visibility:, maar ik kan geen manier bedenken om dat effectief te gebruiken.

Ik heb ook geprobeerd om hoogte te gebruiken, maar dat is gewoon jammerlijk mislukt.

Ik ben me er ook van bewust dat het triviaal is om dit te bereiken met JavaScript, maar ik wilde mezelf uitdagen om alleen CSS te gebruiken, en ik denk dat ik een beetje tekort kom.


Antwoord 1, autoriteit 100%

Je kunt twee of meer overgangen samenvoegen, en visibilityis wat deze keer handig is.

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>

Antwoord 2, autoriteit 56%

Je moet het element op een andere manier verbergen om dit te laten werken.

Ik heb het effect bereikt door beide <div>en absoluut te positioneren en de verborgen in te stellen op opacity: 0.

Als u zelfs de eigenschap displayvan nonenaar blockwisselt, zal uw overgang naar andere elementen niet plaatsvinden.

Om dit te omzeilen, moet het element altijd display: blockzijn, maar verberg het element door een van deze middelen aan te passen:

  1. Stel de heightin op 0.
  2. Stel de opacityin op 0.
  3. Plaats het element buiten het frame van een ander element dat overflow: hiddenheeft.

Er zijn waarschijnlijk meer oplossingen, maar u kunt geen overgang uitvoeren als u het element omschakelt naar display: none. U kunt bijvoorbeeld iets als dit proberen:

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

Maar dat zal nietwerken. Uit mijn ervaring heb ik ontdekt dat dit niets doet.

Hierdoor moet je altijd het element display: blockbehouden – maar je kunt dit omzeilen door zoiets als dit te doen:

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

Antwoord 3, autoriteit 21%

Op het moment van dit bericht schakelen alle belangrijke browsers CSS-overgangen uit als u probeert de displayonroerend goed te wijzigen, maar CSS-animaties werken nog steeds prima, zodat we ze als een oplossing kunnen gebruiken.

Voorbeeldcode (u kunt deze op uw menu dienovereenkomstig toepassen) Demo :

Voeg de volgende CSS toe aan uw stylesheet:

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

Pas vervolgens de fadeInAnimatie toe aan het kind op bovenlevende hover (en natuurlijk ingesteld display: block):

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

Update 2019 – Methode die ook vervaging ondersteunt:

(sommige JavaScript-code is vereist)

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

Antwoord 4, autoriteit 7%

In plaats van callbacks, die niet bestaan in CSS, kunnen we de eigenschap transition-delaygebruiken.

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

Dus, wat is hier aan de hand?

  1. Als de klasse visiblewordt toegevoegd, starten zowel heightals opacityde animatie zonder vertraging (0 ms), hoewel heightheeft 0 ms nodig om de animatie te voltooien (equivalent van display: block) en opacityduurt 600 ms.

  2. Als de klasse visiblewordt verwijderd, start opacityde animatie (0 ms vertraging, 400 ms duur), en wacht de hoogte 400 ms en alleen dan onmiddellijk (0 ms) herstelt de beginwaarde (equivalent van display: nonein de animatie-callback).

Let op, deze aanpak is beter dan die waarbij visibilitywordt gebruikt. In dergelijke gevallen neemt het element nog steeds de ruimte op de pagina in beslag en is het niet altijd geschikt.

Voor meer voorbeelden verwijzen wij u naar dit artikel.


Antwoord 5, autoriteit 6%

Ik vermoed dat de redendat overgangen worden uitgeschakeld als displaywordt gewijzigd, is vanwege wat de weergave feitelijk doet. Het verandert nietsiets dat mogelijk soepel geanimeerd zou kunnen worden.

display: none;en visibility: hidden;zijn twee helemaalverschillende dingen.
Beide hebben het effect dat het element onzichtbaar wordt, maar met visibility: hidden;wordt het nog steeds weergegeven in de lay-out, maar alleen niet zichtbaardus.
Het verborgen element neemt nog steeds ruimte in beslag en wordt nog steeds inline weergegeven of als een blok of block-inline of tabel of wat het display-element ook zegt dat het moet worden weergegeven als, en neemt dienovereenkomstig ruimte in beslag.
Andere elementen worden nietautomatisch verplaatst om die ruimte in te nemen. Het verborgen element geeft zijn werkelijke pixels niet weer aan de uitvoer.

display: noneaan de andere kant voorkomtdat het element geheelwordt weergegeven.
Het neemt geen geenlayoutruimte in beslag.
Andere elementen die een deel of alle ruimte zouden hebben ingenomen die door dit element wordt ingenomen, passen zich nu aan om die ruimte in te nemen, alsof het element gewoon helemaal niet bestond.

displayis niet zomaar een visueel attribuut.
Het bepaalt de volledige weergavemodus van het element, zoals of het een block, inline, inline-block, table, table-row, table-cell, list-itemof wat dan ook!
Elk van deze heeft zeer verschillende lay-outvertakkingen en er zou geen redelijke manier zijn om ze te animeren of soepel over te zetten (probeer een soepele overgang voor te stellen van blocknaar inlineof vice- omgekeerd, bijvoorbeeld!).

Daarom zijn overgangen uitgeschakeld als de weergave verandert (zelfs als de wijziging van of naar noneis — noneis niet alleen onzichtbaarheid, het is zijn eigen weergavemodus voor elementen dat betekent helemaal geen weergave!).


Antwoord 6, autoriteit 4%

displayis niet een van de eigenschappen waarop transitie werkt.

Bekijk Animatable CSS-eigenschappenvoor de lijst met CSS-eigenschappen waarop overgangen kunnen worden toegepast. Zie CSS Values and Units Module Level 4, Combineren Values: Interpolation, Addition , en Accumulatievoor hoe ze worden geïnterpoleerd.

Tot CSS 3 werd vermeld in 9.1. Eigenschappen van CSS(sluit gewoon de waarschuwingspop-up)

Ik heb ook geprobeerd om hoogte te gebruiken, maar dat is gewoon jammerlijk mislukt.

De laatste keer dat ik dit moest doen, gebruikte ik in plaats daarvan max-height, wat een animeerbare eigenschap is (hoewel het een beetje een hack was, werkte het wel), maar pas op dat het kan wees erg janky voor complexe pagina’s of gebruikers met low-end mobiele apparaten.


Antwoord 7, autoriteit 2%

Je kunt nu een aangepaste animatie toevoegen aan de blokeigenschap.

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

Demo

In deze demo verandert het submenu van display:nonein display:blocken kan het nog steeds vervagen.


Antwoord 8, autoriteit 2%

Ik heb een betere manier gevonden voor dit probleem, je kunt CSS-animatie gebruiken en je geweldige effect maken voor het weergeven van items.

.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)
     }
}

Antwoord 9, autoriteit 2%

Volgens W3C Working Draft 19 november 2013displayis geen beweegbare eigenschap. Gelukkig is visibilityanimeerbaar. U kunt de overgang koppelen met een overgang van dekking (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 voor testen:

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

Merk op dat als u de link transparant gewoon maakt, zonder visibility: hidden, dan blijft klikbaar.


10

EDIT: DISPLAY NONE WORDT NIET IN DIT VOORBEELD TOEGEPAST.

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

Wat er hierboven gebeurt, is dat tot en met 99% van het animatiedisplay is ingesteld om te blokkeren terwijl de opaciteit verdwijnt. In het laatste moment is Display-eigenschap ingesteld op Geen.

En het belangrijkste bit is om het laatste frame te behouden nadat de animatie eindigt met behulp van animatie-vulmodus: Forwards

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

Hier zijn twee voorbeelden: https://jsfiddle.net/qwnz9tqg/3/


11

Mijn handige JavaScript-truc is om het hele scenario in twee verschillende functies te verdelen!

Om dingen voor te bereiden, wordt één globale variabele gedeclareerd en één gebeurtenishandler gedefinieerd:

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

Vervolgens, wanneer ik een element verberg, gebruik ik zoiets als dit:

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

Om het element weer te laten verschijnen, doe ik zoiets als dit:

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

Het werkt, tot nu toe!


Antwoord 12

Ik kwam dit vandaag tegen, met een position: fixedmodaal dat ik hergebruikte. Ik kon het niet laten display: noneen het vervolgens animeren, omdat het net verscheen, en en z-index(negatieve waarden, enz.) deden rare dingen als goed.

Ik gebruikte ook een height: 0tot height: 100%, maar het werkte alleen toen het modaal verscheen. Dit is hetzelfde als wanneer je left: -100%of zoiets gebruikt.

Toen viel me op dat er een simpel antwoord was. En voila:

Eerstuw verborgen modal. Merk op dat de height0is, en bekijk de height-declaratie in overgangen… deze heeft een 500ms, die langer is dan mijn opacity-overgang. Onthoud dat dit van invloed is op de uitgaande fade-out-overgang: de modal terugzetten naar de standaardstatus.

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

Ten tweede,uw zichtbare modaal. Stel dat u een .modal-activeinstelt op de body. Nu is de height100%, en mijn overgang is ook veranderd. Ik wil dat de heightonmiddellijk wordt gewijzigd en dat de opacity300msduurt.

.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;
}

Dat is het, het werkt als een tierelier.


Antwoord 13

Op basis van enkele van deze antwoorden en enkele suggesties elders, werkt het volgende uitstekend voor zweefmenu’s (ik gebruik dit met Bootstrap 3, specifiek):

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;
}

U kunt ook heightgebruiken in plaats van max-heightals u beide waarden opgeeft, aangezien height:autoniet is toegestaan met transitions. De zweefwaarde van max-heightmoet groter zijn dan de heightvan het menu eventueel kan zijn.


Antwoord 14

Ik ben dit probleem meerdere keren tegengekomen en heb nu gekozen voor:

.block {
  opacity: 1;
  transition: opacity 250ms ease;
}
.block--invisible {
  pointer-events: none;
  opacity: 0;
}

Door de klasse block--invisibletoe te voegen, zijn de hele elementen niet klikbaar, maar alle elementen erachter zijn vanwege de pointer-events:nonedie wordt ondersteund door alle belangrijke browsers (geen IE < 11).


15

Ik heb eindelijk een oplossing voor mij gevonden door opacityte combineren met position absolute(niet om ruimte te bezetten wanneer het verborgen is).

.toggle {
  opacity: 0;
  position: absolute;
  transition: opacity 0.8s;
}
.parent:hover .toggle {
  opacity: 1;
  position: static;
}

16

JavaScript is niet vereist en er is geen waanzinnige enorme maximale hoogte nodig. Stel in plaats daarvan uw max-heightin op uw tekstelementen en gebruik een lettertype-relatieve eenheid zoals remof em. Op deze manier kunt u een maximale hoogte groter instellen dan uw container, terwijl u een vertraging of “knallen” vermijden wanneer het menu sluit:

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
}

Zie hier een voorbeeld:
http://codepen.io/mindfullsilence/pen/dtzje


17

Nadat het geaccepteerde antwoord van Guillermo is geschreven, de CSS
Overgangspecificatie van 2012-04-03 veranderde het gedrag van de zichtbaarheidsovergang en nu is het mogelijk om dit probleem op een kortere manier op te lossen, zonder het gebruik van overgangsvertraging:

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

De vervolgkeuzelijst voor beide overgangen moet meestal zijn
identiek (hoewel een iets langere tijd voor zichtbaarheid geen probleem is).

Zie mijn blog post CSS-transitie zichtbaarheid .

W.R.T. De titel van de vraag “overgangen op het display: onroerend goed” en in reactie op opmerkingen van RUI Marques en Josh naar het geaccepteerde antwoord:

Deze oplossing werkt in de gevallen waar het irrelevant is als het display of
Zichtbaarheidseigenschap wordt gebruikt
(zoals het waarschijnlijk het geval was in deze vraag).

Het zal het element niet volledig verwijderen als display:none, maak het gewoon onzichtbaar, maar het blijft nog steeds in de documentstroming en beïnvloedt de positie van de volgende elementen.

Overgangen die het element volledig verwijderen, vergelijkbaar met display:nonekan worden gedaan met behulp van de hoogte (zoals aangegeven door andere antwoorden en opmerkingen), max-hoogte of margin-top / onderkant, maar ook zien
Hoe kan ik hoogte: 0; naar hoogte: automatisch; CSS gebruiken?en mijn blogpost Oplossingen voor CSS-overgangen op de weergave- en hoogte-eigenschappen.

In reactie op commentaar van GeorgeMillo:
Beide eigenschappen en beide overgangen zijn nodig: De eigenschap dekking
wordt gebruikt om een fade-in en fade-out animatie te maken en de zichtbaarheid
eigenschap om te voorkomen dat het element nog steeds reageert op de muis
evenementen. Overgangen zijn nodig op de dekking voor het visuele effect en op
zichtbaarheid om het verbergen uit te stellen totdat de fade-out is voltooid.


Antwoord 18

Het is zo simpel als het volgende 🙂

@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;

Laat het vervagen en maak het dan height 0;. Zorg er ook voor dat je forwards gebruikt, zodat het in de definitieve staat blijft.


Antwoord 19

Vervaag het met CSS-animaties:

.item {
     display: none;
}
.item:hover {
     display: block;
     animation: fadeIn 0.5s;
}
@keyframes fadeIn {
     from {
          opacity: 0;
     }
     to {
          opacity: 1;
     }
}

Antwoord 20

Ik vermoed dat iedereen die net begint met CSS-overgangen, snel ontdekt dat ze niet werken als je tegelijkertijd de eigenschap display (blokkeren/geen) aanpast. Een tijdelijke oplossing die nog niet is genoemd, is dat u display:block/nonekunt blijven gebruiken om het element te verbergen/weergeven, maar de dekking op 0 te zetten zodat zelfs wanneer het display:block, het is nog steeds onzichtbaar.

Om het vervolgens in te faden, voegt u een andere CSS-klasse toe, zoals “on”, die de dekking instelt op 1 en de overgang voor dekking definieert. Zoals je je misschien hebt voorgesteld, moet je JavaScript gebruiken om die “on” -klasse aan het element toe te voegen, maar je gebruikt tenminste nog steeds CSS voor de daadwerkelijke overgang.

P.S. Als u zich in een situatie bevindt waarin u zowel display:blockals klasse “on” moet toevoegen, stel de laatste dan uit met behulp van setTimeout. Anders ziet de browser gewoon dat beide dingen tegelijk gebeuren en schakelt de overgang uit.


Antwoord 21

Je kunt dit op de natuurlijke manier laten werken die je had verwacht – met behulp van display – maar je moet de browser vertragen om het te laten werken, met Javascript of zoals anderen een mooie truc hebben voorgesteld met de ene tag in de andere. Ik geef niet om de binnentag omdat het CSS en afmetingen verder compliceert, dus hier is de Javascript-oplossing:

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

Begin met een vak zoals:

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

Een verborgen vak.

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

We gaan een truc gebruiken die gevonden is in een gerelateerde vraag/a, door offsetHeight te controleren om de browser onmiddellijk te vertragen:

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

Eerst een bibliotheek die bovenstaande truc formaliseert:

$.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;
    });
};

Vervolgens gaan we het gebruiken om een kader te onthullen en het in te faden:

$('#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 });
});

Hiermee vervaagt het vak in en uit. Dus .noTrnsn()schakelt overgangen uit, daarna verwijderen we de klasse hidden, die displayomdraait van nonenaar zijn standaard, block. Vervolgens zetten we de dekking op 0 om ons klaar te maken voor infaden. Nu we het podium hebben ingesteld, zetten we overgangen weer aan, met .resumeTrnsn(). En tot slot, start de overgang door de dekking in te stellen op 1.

Zonder de bibliotheek zouden zowel de wijziging in weergave als de wijziging in dekking ons ongewenste resultaten hebben opgeleverd. Als we de bibliotheekoproepen gewoon zouden verwijderen, zouden we helemaal geen overgangen krijgen.

Houd er rekening mee dat het bovenstaande de weergave aan het einde van de fadeout-animatie niet opnieuw op geen zet. We kunnen echter liefhebber worden. Laten we dat doen met een die vervaagt en in hoogte groeit vanaf 0.

Fijn!

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

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

We veranderen nu zowel de hoogte als de dekking. Merk op dat we geen hoogte instellen, wat betekent dat dit de standaard is, auto. Conventioneel kan dit niet worden overgezet – als u van auto naar een pixelwaarde (zoals 0) gaat, krijgt u geen overgang. We gaan dat omzeilen met de bibliotheek, en nog een bibliotheekmethode:

$.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();
    });
};

Dit is een handige methode waarmee we kunnen deelnemen aan de bestaande fx/animation-wachtrij van jQuery, zonder dat we het animatieframework nodig hebben dat nu is uitgesloten in jQuery 3.x. Ik ga niet uitleggen hoe jQuery werkt, maar het volstaat te zeggen dat de .queue()en .stop()leidingen die jQuery biedt ons helpen voorkomen dat onze animaties op elkaar stappen.

Laten we het effect naar beneden animeren.

$('#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');
        });
    }
});

Deze code begint met het controleren van #boxen of het momenteel verborgen is, door de klasse te controleren. Maar het bereikt meer met de bibliotheekaanroep wait(), door de klasse hiddentoe te voegen aan het einde van de slideout/fade-animatie, die je zou verwachten als het is in feite verborgen – iets wat het bovenstaande eenvoudigere voorbeeld niet kon doen. Dit zorgt er ook voor dat het element keer op keer wordt weergegeven/verbergt, wat een fout was in het vorige voorbeeld, omdat de verborgen klasse nooit is hersteld.

Je kunt ook CSS- en klassewijzigingen zien die worden aangeroepen na .noTrnsn()om in het algemeen de basis te leggen voor animaties, inclusief het nemen van metingen, zoals het meten van wat de uiteindelijke hoogte van #boxzonder dat aan de gebruiker te laten zien, voordat je .resumeTrnsn()aanroept, en het animeert van die volledig ingestelde fase naar zijn doel-CSS-waarden.

Oud antwoord

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

Je kunt het bij klikken laten overschakelen met:

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);

De CSS is wat je zou raden:

.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);
}

De sleutel is het beperken van de weergave-eigenschap. Door de verborgen klasse te verwijderen en vervolgens 50 ms te wachten, en dande overgang te starten via de toegevoegde klasse, zorgen we ervoor dat deze verschijnt en vervolgens uitbreidt zoals we wilden, in plaats van dat het gewoon op het scherm springt zonder enige animatie. Hetzelfde gebeurt in de andere richting, behalve dat we wachten tot de animatie voorbij is voordat we hidden toepassen.

Opmerking: ik maak hier misbruik van .animate(maxWidth)om setTimeoutrace-omstandigheden te vermijden. setTimeoutintroduceert snel verborgen bugs wanneer jij of iemand anders code oppikt die zich er niet van bewust is. .animate()kan gemakkelijk worden gedood met .stop(). Ik gebruik het alleen om een vertraging van 50 ms of 2000 ms in de standaard fx-wachtrij te plaatsen, waar het gemakkelijk te vinden/op te lossen is door andere programmeurs die hier bovenop bouwen.


Antwoord 22

De eenvoudigste universele oplossing voor het probleem is: voel je vrij om display:noneop te geven in je CSS, maar je zult het moeten veranderen in block(of wat dan ook) JavaScript gebruikt, en dan moet je ook een klasse aan je element in kwestie toevoegen die de overgang met setTimeout()daadwerkelijk uitvoert. Dat is alles.

D.w.z.:

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

Dit is getest in de nieuwste, normale browsers. Uiteraard zou het niet moeten werken in Internet Explorer 9 of eerder.


Antwoord 23

Deze oplossing is uitstekend compatibel en ik heb hem nog niet gezien:

.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;
}

Uitleg: het gebruikt de truc visibility: hidden(die compatibel is met “show-and-animate” in één stap), maar het gebruikt de combinatie position: absolute; z-index: -1; pointer-events: none;om ervoor te zorgen dat de verborgen container geen ruimte inneemten niet reageert op gebruikersinteracties.


Antwoord 24

Ik had een soortgelijk probleem waar ik het antwoord niet op kon vinden. Een paar Google-zoekopdrachten later brachten me hier. Aangezien ik niet het eenvoudige antwoord vond waarop ik hoopte, stuitte ik op een oplossing die zowel elegant als effectief is.

Het blijkt dat de CSS-eigenschap visibilityeen waarde collapseheeft die over het algemeen wordt gebruikt voor tabelitems. Als het echter op andere elementen wordt gebruikt, worden ze effectief weergegeven als verborgen, vrijwel hetzelfde als display: hiddenmaar met de toegevoegde mogelijkheid dat het element geen gebruik maakt elke spatie en je kunt het betreffende element nog steeds animeren.

Hieronder ziet u een eenvoudig voorbeeld hiervan in actie.

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>

Antwoord 25

Ik denk dat SalmanPK het beste antwoord heeft. Het vervaagt een item in of uit, met de volgende CSS-animaties. De eigenschap display animeert echter niet soepel, alleen de dekking.

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

Als je het element wilt animeren dat van weergaveblok naar geen weergave gaat, zie ik niet dat dit momenteel alleen mogelijk is met CSS. Je moet de hoogte krijgen en een CSS-animatie gebruiken om de hoogte te verkleinen. Dit is mogelijk met CSS, zoals weergegeven in het onderstaande voorbeeld, maar het zou lastig zijn om de exacte hoogtewaarden te weten die u voor een element moet animeren.

jsFiddlevoorbeeld

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";

26

U kunt dit doen met transitie-evenementen, dus u bouwt twee CSS-klassen voor de overgang, één die de animatie heeft ingedrukt, met behulp van het display Geen State. En je wisselt ze nadat de animatie is beëindigd? In mijn geval kan ik de DIV’s opnieuw weergeven als ik op een knop druk op en verwijder beide klassen.

Probeer het fragment hieronder …

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

27

Nou, een andere manier om in deze situatie een overgang toe te passen zonder gebruik te maken van keyframes, is door de breedtevan je element in te stellen op nulen het vervolgens uit te schakelen bij zweven

.className{
  visibility:hidden;
  opacity: 0;
  transition: .2s;
  width:0;
}
.className:hover{
  visibility:visible;
  margin-right: .5rem;
  opacity: 1;
  width:unset;
}

Antwoord 28

Ik waardeer alle antwoorden. Dit is wat ik voor vergelijkbare doeleinden gebruik: overgang versus animatie.

Voorbeeld: https://jsfiddle.net/grinevri/tcod87Le/22/

<div class="animation"></div>
<div class="transition"></div>
@keyframes animationTo {
  0% { background-color: rgba(0, 0, 0, 0.1); }
  100% { background-color: rgba(0, 0, 0, 0.5); }
}
@keyframes animationFrom {
  0% { background-color: rgba(0, 0, 0, 0.5); }
  100% { background-color: rgba(0, 0, 0, 0.1); }
}
.animation,
.transition{
  margin: 5px;
  height: 100px;
  width: 100px;
  background-color: rgba(0, 0, 0, 0.1);
}
.animation{
  animation: animationFrom 250ms;
}
.animation:hover{
  background-color: rgba(0, 0, 0, 0.5);
  animation: animationTo 250ms;
}
.transition{
  transition: background-color 250ms;
}
.transition:hover{
  background-color: rgba(0, 0, 0, 0.5);
}

Antwoord 29

Als je jQuery gebruikt om je lessen in te stellen, werkt dit 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>

Other episodes