CSS min-height not resizing based on content - html

I am currently trying to make content appear when a label is selected. The issue which I am having is that the content which will appear will vary in size based on the data which is being pulled in so I cannot set a specific height which will work in all cases. I thought the best way to work around this was to use min-height but the height doesn't seem to be betting itself based on the length of the size of the content. How can I fix this o that the size will be based on how much content there is.
#block {
background: yellow;
height: 0;
overflow: hidden;
-webkit-transition: height 300ms linear;
-moz-transition: height 300ms linear;
-o-transition: height 300ms linear;
transition: height 300ms linear;
}
label {
cursor: pointer;
}
#showContent {
display: none;
}
#showContent:checked+#block {
min-height: 5px;
}
#showContent:not(:checked) {
height: 0px;
}
<label for="showContent">Show content</label>
<input type="checkbox" id="showContent" />
<div id="block">
Show content ..... Bla bla bla
</div>
jsfiddle
https://jsfiddle.net/sacora9/81m14v1s/14/

Just set the height to auto. Otherwise, you set min-height:5px, but the height is still set to 0, so the calculated height will be 5px. So the solution is to release the height and make it free :
#block {
background: yellow;
height: 0;
overflow: hidden;
-webkit-transition: height 300ms linear;
-moz-transition: height 300ms linear;
-o-transition: height 300ms linear;
transition: height 300ms linear;
}
label {
cursor: pointer;
}
#showContent {
display: none;
}
#showContent:checked+#block {
height : auto; /* <----- Here, instead of min-height: 5px */
}
#showContent:not(:checked) {
height: 0px;
}
<label for="showContent">Show content</label>
<input type="checkbox" id="showContent" />
<div id="block">
Show content ..... Bla bla bla
</div>
EDIT
I've just noticed the animation part. Transition from 0 to auto is tricky, but here's the trick :
#block {
background: yellow;
overflow: hidden;
max-height: 0;
transition: max-height 0.3s cubic-bezier(0,1,0,1);
}
label {
cursor: pointer;
}
#showContent {
display: none;
}
#showContent:checked+#block {
max-height: 1000px;
transition: max-height 0.3s cubic-bezier(1,0,1,0);
}
#showContent:not(:checked) {
height: 0px;
}
<label for="showContent">Show content</label>
<input type="checkbox" id="showContent" />
<div id="block">
Show content ..... Bla bla bla
</div>

On your example, block still has height: 0; applied to it even when showContent is checked. Instead, set the height to auto.

One way to do this while maintaining the animation would be to use max-height instead:
#block {
background: yellow;
max-height: 0px;
overflow: hidden;
-webkit-transition: max-height 300ms linear;
-moz-transition: max-height 300ms linear;
-o-transition: max-height 300ms linear;
transition: max-height 300ms linear;
}
label {
cursor: pointer;
}
#showContent {
display: none;
}
#showContent:checked + #block {
max-height: 100px; /*any value larger than the content */
}
#showContent:not(:checked){
height:0px;
}

Related

Transition accordion: roll down works, but not roll back up

I am trying to make the accordion roll down, when selected, and roll back up when closed. It rolls down, but when closed it just closes without transition.
I tried adding max-height to the elements, and then using transition: max-height 1s ease-in/ease-out, but it doesn't work for rolling back up :(
I guess I am doing something wrong, but I am still new at web-development, so it's a bit hard to see my own mistakes :P
$('.topic-container').on('click', function() {
if ($(this).hasClass('active')) {
$(this).removeClass('active')
$(this).addClass('closed')
} else {
$(this).addClass('active')
$(this).removeClass('closed')
.siblings()
.removeClass('active')
.addClass('closed')
}
});
.accordion .content {
position: relative;
height: 0;
font-size: 20px;
text-align: justify;
width: 100%;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
max-height: 0;
transition: max-height 1s ease;
}
.accordion .topic-container.active .content {
height: 100%;
max-height: 1000px;
transition: max-height 1s ease-in;
}
.accordion .topic-container.closed .content {
height: 0;
max-height: 0;
transition: max-height 1s ease-out;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="accordion-body">
<div class="accordion">
<div class="topic-container closed">
<div class="label">
Header
</div>
<div class="content">
Inside the accordion tab
</div>
</div>
</div>
</div>
Instead of using max-height 1s ease-out you have to use max-height 1s, height 1s ease-out for transition property
.accordion .topic-container.active .content {
height: 100%;
max-height: 1000px;
transition: max-height 1s, height 1s ease-in;
}
.accordion .topic-container.closed .content {
height: 0;
max-height: 0;
transition: max-height 1s, height 1s ease-out;
}

Move div according to other div's height

I have two divs and I want to move both of them at the same time: one to left and other to up.
I did that using the transfom CSS property and I set the translateX and translateY in pixels.
How can I do the same effect when I don't know the height of first div? It's addaptive according to its content.
My real project uses Angular and I want to avoid using pure JQuery (a pure CSS solution will be great!).
EDIT:
I use the class above to animate my second div:
.to-up {
transition-delay: .2s;
transform: translateY(-127px);
}
I came to that value of 127px through this calculation:
div1 height + div1 margin-bottom + div1 borders.
In my real case, the div1 height is addaptive to its content so I don't know how to animate div2 to the top of its parent. How can I do that?
Here's my HTML:
<div class="container">
<div id="item1" class="item">Test1</div>
<div id="item2" class="item">Test2</div>
</div>
My CSS:
.container {
width: 100%;
}
#item1 {
height: 120px;
}
#item2 {
height: 80px;
}
.item {
width: 100px;
border: 1px solid black;
margin: 5px;
transition: all .3s ease-in-out;
-webkit-transition: all .3s ease-in-out;
-moz-transition: all .3s ease-in-out;
-ms-transition: all .3s ease-in-out;
-o-transition: all .3s ease-in-out;
}
.to-right {
transform: translateX(-107%);
}
.to-up {
transition-delay: .2s;
transform: translateY(-127px);
}
And JQuery:
$('.item').on('click', function() {
$('#item1').toggleClass('to-right');
$('#item2').toggleClass('to-up');
});
Finally there's the code working with pixels on Jsfiddle.
Thanks a lot!
This is the better solution that you can do, with Angular in template (don't forget the "goOn" variable initialization in the component):
<div class="container">
<div id="item1" class="item" [class.to-right]="goOn" (click)="goOn = !goOn">Test1</div>
<div id="item2" class="item" [class.to-up]="goOn" (click)="goOn = !goOn">Test2</div>
</div>
Here a working example: https://stackblitz.com/edit/angular-animation-on-click?file=src/app/app.component.html
I think you can't do it without angular (or js) because we're talking about "click" event.
I'm not understanding about what do you want to do without knowing the box heights. Where do you want to move them? I think that without knowing its solution you can't do it.
Problem fixed.
Instead using translateY property to move the second div I used animation with animation-timing-function as linear and animation-fill-mode as forwards.
What did I changed?
Container element now has relative position.
An animation called top was created (set top to 0 on 100%).
The class .move-up changes element position to absolute and call the top animation.
I set .move-up class to the second div on click.
Here's a working poc on Jsfiddle.
HTML:
<div class="container">
<div id="item1" class="item">Test1</div>
<div id="item2" class="item">Test2</div>
</div>
JQuery:
$('.item').on('click', function() {
$('#item1').toggleClass('to-right');
$('#item2').toggleClass('to-top');
});
CSS:
.container {
width: 100%;
position: relative;
}
#item1 {
height: 120px;
}
#item2 {
height: 80px;
margin-top: 0px;
}
.item {
width: 100px;
border: 1px solid black;
margin: 5px;
transition: all .3s ease-in-out;
-webkit-transition: all .3s ease-in-out;
-moz-transition: all .3s ease-in-out;
-ms-transition: all .3s ease-in-out;
-o-transition: all .3s ease-in-out;
}
.to-right {
transform: translateX(-107%);
}
.to-top {
position: absolute;
animation-name: top;
animation-duration: .3s;
animation-delay: .2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
}
#keyframes top {
0% {
top: 100%;
}
100% {
top: 0;
}
}

Center both elements like "display: none;"

.Button_Image {
width: 40px;
-webkit-transition: opacity 0.5s linear;
-moz-transition: opacity 0.5s linear;
-ms-transition: opacity 0.5s linear;
-o-transition: opacity 0.5s linear;
opacity: 1;
}
.Button:hover .Button_Image {
opacity: 0;
}
.Button_Name {
font-size: 18px;
color: black;
line-height: 40px;
-webkit-transition: opacity 0.5s linear;
-moz-transition: opacity 0.5s linear;
-ms-transition: opacity 0.5s linear;
-o-transition: opacity 0.5s linear;
opacity: 0;
}
.Button:hover .Button_Name {
opacity: 1;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<a href="#" class="Button btn btn-success btn-block">
<img class="Button_Image" src="https://i.stack.imgur.com/hiAkR.png">
<span class="Button_Name">Football</span>
</a>
I have a button which has 2 elements inside.
Image of a sport
Name of the sport
When either of these have the css value display: none; the visible one is aligned to center perfectly.
But I needed to add a fade-in-out functionality, so I wasn't able to use display keyword. Instead I went for opacity.
Which resulted these 2 elements to stay side by side even if one is hidden.
How can I center these, when the other one is hidden?
This image has been captured during the transmission event:
The current state is like this:
But I need it like this:
You can achieve what you want with absolute positioning of the image. Is something like this what you want?:
.sportbtn {
border: green 1px solid;
width: 150px;
height: 40px;
position: relative;
line-height: 40px;
}
.sportimg {
/* centered in button */
width: 30px;
transition: left 1s, margin-left 1s;
position: absolute;
left: 50%;
margin-left: -15px; /* half the image width */
margin-top: 5px;
}
.sportname {
transition: opacity 1s;
opacity: 0;
margin-left: 40px;
}
.sportbtn:hover .sportname {
opacity: 1;
}
.sportbtn:hover .sportimg {
margin-left: 0px;
left: 5px;
}
<div class="sportbtn">
<img class="sportimg" src="https://d30y9cdsu7xlg0.cloudfront.net/png/23344-200.png" />
<span class="sportname">Football</span>
</div>

Multiline container unfolding animation

How should CSS multiline container (e.g. content block or alert) unfolding animation should be managed?
http://plnkr.co/edit/Qq5fzeb3GBengviVNimC?p=preview
.alert {
background: turquoise;
color: white;
padding: 10px;
overflow: hidden;
opacity: 0;
max-height: 0;
}
body:hover .alert {
display: block !important;
opacity: 1;
-webkit-transition: 2s;
-moz-transition: 2s;
-ms-transition: 2s;
transition: 2s;
max-height: 100px;
}
The problem here is 'multiline', as you can see, the block height isn't a fixed value.
<div class="alert">Alert!<br>Alert!<br>Alert!</div>
While max-height: 100px is near real block height, it works fine. If max-height is smaller, the animation would be jaggy in the end, and max-height: 9999px will make the transition too fast.
Can this be done without calculating the exact height in JS?
Calculating the height can be done in jQuery indeed, I did the following to solve your problem:
$("#out").html("Block height: " + $("#alert").height());
//solely for demonstration, you can delete this line
$("#alert").css('height','0px');
$('#alert').mouseover( function(){
$("#alert").css('height', '58px');
});
$('#alert').mouseout( function(){
$("#alert").css('height', '0px');
});
#alert {
background: turquoise;
color: white;
padding: 10px;
overflow: hidden;
opacity: 0;
//max-height: 0; this causes .height() to always display '0' so delete this here, and set this via jQuery
}
body:hover #alert {
display: block !important;
opacity: 1;
-webkit-transition: 2s;
-moz-transition: 2s;
-ms-transition: 2s;
transition: 2s;
// max-height: 100px !important; set this via jQuery
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p>Hello!</p>
<div id="alert">Alert!<br>Alert!<br>Alert!</div>
<p>Hello again!</p>
<span id="out"></span>

A 'light swtch' to toggle text and background colours for a full page using CSS

I'm trying to create a 'light switch' with CSS to toggle the colours of a page. I've made a bad start using Joe's excellent response to this question: Change background on button click, using CSS only?
Is it possible to target the whole page rather than content inside divs? Also: can I do anything more to disguise the button as a link?
http://jsfiddle.net/gd4dma64/
HTML:
<label for="check" class="lights">Click here to invert colours</label>
<input type="checkbox" id="check" />
<div>This works...</br>
but how about links (and the button itself)...
</div>
<p>and how about the full page (without containing everything in a div)?</p>
CSS:
body, a {
color: #000
}
div {
-webkit-transition: all 0.5s linear;
-moz-transition: all 0.5s linear;
-ms-transition: all 0.5s linear;
-o-transition: all 0.5s linear;
transition: all 0.5s linear;
}
input[type="checkbox"] {
display: none;
}
input[type="checkbox"]:checked + div {
background: #000;
color: #fff;
}
Thank you for looking - and apologies, I'm really naive.
Hey you must change your css like this:
input[type="checkbox"]:checked + label +div,
input[type="checkbox"]:checked + label +div>a
,input[type="checkbox"]:checked+label {
background: #000;
color: #fff;
}
And the html like this:
<input type="checkbox" id="check" />
<label for="check" class="lights">Click here to invert colours</label>
<div>This works...<br>
but how about links (and the button itself)...
</div>
<p>and how about the full page (without containing everything in a div)?</p>
You can make the <div> as position:absolute page wise, and set z-index:-1; so it will be under your normal content.
body, a {
color: #666;
}
div {
-webkit-transition: all 0.5s linear;
-moz-transition: all 0.5s linear;
-ms-transition: all 0.5s linear;
-o-transition: all 0.5s linear;
transition: all 0.5s linear;
}
input[type="checkbox"] {
display: none;
}
input[type="checkbox"]:checked + div {
background: #000;
color: #fff;
}
/*added code below*/
body {
margin: 0;
}
div {
position: absolute;
width: 100%;
height: 100%;
z-index: -1;
left: 0;
top: 0;
}
<label for="check" class="lights">Click here to invert colours</label>
<input type="checkbox" id="check" />
<div></div>