I'm building a website that has some state transitions using only CSS. In one of them the user clicks on the header and the div
below displays or hides. In the other there is a sequence of images and clicking on the current image it moves to the next one. The technique for both is similar: a input
hidden with one or more label
s attached to it, and the CSS selectors of "brothers" ( +
and ~
). Examples:
.escondido { display: none; }
.box { display: none; width: 200px; height: 100px; }
.escondido:checked + .box { display: block; }
h2 { width: 200px; background-color: lightgray; cursor: pointer; }
.a { background-color: red; }
.b { background-color: blue; }
<label for="aba1"><h2>Seção 1</h2></label>
<input id="aba1" class="escondido" type="checkbox">
<div class="box a"></div>
<label for="aba2"><h2>Seção 2</h2></label>
<input id="aba2" class="escondido" type="checkbox">
<div class="box b"></div>
.escondido { display: none; }
.imagem { display:none; width: 200px; height: 100px; cursor: pointer; }
.escondido:checked + label .imagem { display: block; }
.a { background-color: red; }
.b { background-color: blue; }
.c { background-color: green; }
.d { background-color: yellow; }
.mini { display: inline-block; width: 10px; height: 10px; border-radius: 5px; }
.escondido.a:checked ~ label .mini.a { border: 2px solid black; }
.escondido.b:checked ~ label .mini.b { border: 2px solid black; }
.escondido.c:checked ~ label .mini.c { border: 2px solid black; }
.escondido.d:checked ~ label .mini.d { border: 2px solid black; }
<!-- Imagens -->
<input id="img1" class="escondido a" type="radio" name="imgs" checked>
<label for="img2"><div class="imagem a"></div></label>
<input id="img2" class="escondido b" type="radio" name="imgs">
<label for="img3"><div class="imagem b"></div></label>
<input id="img3" class="escondido c" type="radio" name="imgs">
<label for="img4"><div class="imagem c"></div></label>
<input id="img4" class="escondido d" type="radio" name="imgs">
<label for="img1"><div class="imagem d"></div></label>
<!-- Miniaturas -->
<label for="img1"><div class="imagem mini a"></div></label>
<label for="img2"><div class="imagem mini b"></div></label>
<label for="img3"><div class="imagem mini c"></div></label>
<label for="img4"><div class="imagem mini d"></div></label>
I would now like to animate the transition between the "displayed" and "hidden" states. I know it's not possible to animate the display
property directly: jQuery for example at the time of displaying first reduces the element size to zero, passes display
from "hidden" to "displayed", then animates element size from zero to its actual size. I can not do something similar with just CSS, because you can not say "first do this, then do that" ...
I tried to avoid the display
and simply put the total height of div
to zero. It worked fine if div
has fixed size, but not if size is variable (it "jumped" straight between zero and maximum sizes):
.escondido { display: none; }
.box { height: 0; width: 200px; overflow: hidden; transition: height 2s; }
h2 { width: 200px; background-color: lightgray; cursor: pointer; }
.a { background-color: red; }
.b { background-color: lightgray; }
.escondido:checked + .a { display: block; height: 100px; }
.escondido:checked + .b { display: block; height: auto; }
<label for="aba1"><h2>funciona</h2></label>
<input id="aba1" class="escondido" type="checkbox">
<div class="box a"></div>
<label for="aba2"><h2>não funciona</h2></label>
<input id="aba2" class="escondido" type="checkbox">
<div class="box b">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
(I also tried with max-height
, and it also worked on div
fixed, but in this case the variable size was not displayed ...)
Is it possible to do this with CSS only, without having to specify an absolute size? (and without compromising responsiveness, ie if by adjusting the width of the window the height of the% change, keep it working) What properties could I try to animate to create the illusion of "hidden / displayed" with smooth transition? >
Note: In the case of images, the exchange would be horizontal and not vertical, but because it is easier to deal with images (since it is usually known), this case can be left out of the question (but suggestions for this would also be very welcome).