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: none
om 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 visibility
is 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 display
van none
naar block
wisselt, zal uw overgang naar andere elementen niet plaatsvinden.
Om dit te omzeilen, moet het element altijd display: block
zijn, maar verberg het element door een van deze middelen aan te passen:
- Stel de
height
in op0
. - Stel de
opacity
in op0
. - Plaats het element buiten het frame van een ander element dat
overflow: hidden
heeft.
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: block
behouden – 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 display
onroerend 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 fadeIn
Animatie 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-delay
gebruiken.
#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?
-
Als de klasse
visible
wordt toegevoegd, starten zowelheight
alsopacity
de animatie zonder vertraging (0 ms), hoewelheight
heeft 0 ms nodig om de animatie te voltooien (equivalent vandisplay: block
) enopacity
duurt 600 ms. -
Als de klasse
visible
wordt verwijderd, startopacity
de animatie (0 ms vertraging, 400 ms duur), en wacht de hoogte 400 ms en alleen dan onmiddellijk (0 ms) herstelt de beginwaarde (equivalent vandisplay: none
in de animatie-callback).
Let op, deze aanpak is beter dan die waarbij visibility
wordt 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 display
wordt 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: none
aan 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.
display
is 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-item
of 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 block
naar inline
of vice- omgekeerd, bijvoorbeeld!).
Daarom zijn overgangen uitgeschakeld als de weergave verandert (zelfs als de wijziging van of naar none
is — none
is niet alleen onzichtbaarheid, het is zijn eigen weergavemodus voor elementen dat betekent helemaal geen weergave!).
Antwoord 6, autoriteit 4%
display
is 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;
}
In deze demo verandert het submenu van display:none
in display:block
en 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 2013display
is geen beweegbare eigenschap. Gelukkig is visibility
animeerbaar. 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: fixed
modaal dat ik hergebruikte. Ik kon het niet laten display: none
en het vervolgens animeren, omdat het net verscheen, en en z-index
(negatieve waarden, enz.) deden rare dingen als goed.
Ik gebruikte ook een height: 0
tot 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 height
0
is, 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-active
instelt op de body
. Nu is de height
100%
, en mijn overgang is ook veranderd. Ik wil dat de height
onmiddellijk wordt gewijzigd en dat de opacity
300ms
duurt.
.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 height
gebruiken in plaats van max-height
als u beide waarden opgeeft, aangezien height:auto
niet is toegestaan met transition
s. De zweefwaarde van max-height
moet groter zijn dan de height
van 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--invisible
toe te voegen, zijn de hele elementen niet klikbaar, maar alle elementen erachter zijn vanwege de pointer-events:none
die wordt ondersteund door alle belangrijke browsers (geen IE < 11).
15
Ik heb eindelijk een oplossing voor mij gevonden door opacity
te 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-height
in op uw tekstelementen en gebruik een lettertype-relatieve eenheid zoals rem
of 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:none
kan 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/none
kunt 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:block
als 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 display
omdraait van none
naar 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 #box
en of het momenteel verborgen is, door de klasse te controleren. Maar het bereikt meer met de bibliotheekaanroep wait()
, door de klasse hidden
toe 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 #box
zonder 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 setTimeout
race-omstandigheden te vermijden. setTimeout
introduceert 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:none
op 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 visibility
een waarde collapse
heeft 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: hidden
maar 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>