12
I’m building a site that has some state transitions using CSS only. In one of them the user clicks the header and the div
below displays or hides. In the other there is a sequence of images and when clicking on the current image it passes to the next one. The technique for both is similar: a input
hidden with one or more label
s linked to it, and the CSS selectors of "brothers" (+
and ~
). Examples:
- Sections (uses checkboxes to hide/show each section)
.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>
- Images (usa radio Buttons to circulate between images)
.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 is not possible to animate the property display
directly: jQuery for example when showing first reduces the size of the element to zero, passes the display
from "hidden" to "displayed", then animate the size of the element from zero to its actual size. I can’t do something like that with just CSS, because you can’t say, "First do this, then do that"...
I tried to avoid the display
and simply place the full height of the div
at zero. It worked well if the div
has fixed size, but not if size is variable (she "jumped" directly 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 also worked on div
fixed size, but in this case the variable size was not displayed...)
Is it possible to do this only with CSS, without specifying an absolute size? (and without compromising responsiveness, i.e. if by adjusting the width of the window the height of the div
change, keep running) What properties I could 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 as it is easier to deal with images (because usually its size is known) this case can be left out of the question (but suggestions for this case would also be very welcome).
But then you’ll cut the text if it’s bigger, no?
– Bacco
yes, but one can define a
max-height
major, the only problem is that in doing so the transition will be affected by now calculating to a higher height– Chun
As @Bacco commented, unless I put a
max-height
large enough to ensure that the content will never be greater than it, may occur overflow... Funny that I had already tried this, but it hadn’t worked, but your example works. The biggest problem is (this you just commented on... : P)– mgibsonbr
Anyway, +1, because using a easing adequate this solution can be good enough in the absence of other.
– mgibsonbr