I am having issues coming up with a way to make a child have transitionable width while making the parent change instantaneously.
Using the following example:
.parent {
height: 100px;
width: 25%;
background-color: blue;
}
.child {
width: 100%;
transition: width 1s;
background-color: red;
height: 50px;
}
.parent:hover {
width: 50%;
}
<div class="parent">
<div class="child">
</div>
</div>
When .parent is hovered, its width should increase, and then the child should take 1s to catch up to the parents width.
Is there any way to achieve this? I don't want the parent to transition as it will cause a lot of jumping around as the parent grows instead of moving everything at once.
You can't use transition, since the child's width value doesn't actually change - it was 100% before and 100% after.
In this case you can use an animation that will start from 50% if the new width, and proceed to the 100%. If the hover ends, the child width will go back to the parent's width immediately.
.parent {
height: 100px;
width: 25%;
background-color: blue;
}
.child {
width: 100%;
background-color: red;
height: 50px;
}
.parent:hover {
width: 50%;
}
.parent:hover .child {
animation: 1s both grow;
}
#keyframes grow {
from { width: 50%; }
to { width: 100%; }
}
<div class="parent">
<div class="child">
</div>
</div>
So keep in mind that div elements are block elements. They will fill the full-width of their parent unless you style them otherwise.
This makes using percentages problematic without adding a keyframes animation. Though there is nothing wrong with defining an animation.
But if you give exact widths with other types of css units, you can achieve the affect by also changing the width of the child when the parent is hovered.
Below I changed the parent width to 25vw and assigned the same width to the child. Then, when the parent is hovered, change the child width to 100% will cause it to transition.
In the original case, you were only changing the parents width, and the child's width never transitioned because in both states of the parent, its value was 100%.
.parent {
height: 100px;
width: 25vw;
background-color: blue;
}
.child {
width: 25vw;
transition: width 1s linear;
background-color: red;
height: 50px;
}
.parent:hover {
width: 50%;
}
.parent:hover > .child {
width: 100%;
}
<div class="parent">
<div class="child">
</div>
</div>
The issue is that you're child's width is technically not changing. It remains 100% of the parent's width, so though it's physical size as constrained within the parent changes, it's relative width value is still 100%, so no transition is being applied to it.
Using vw units will allow you to create a fluid layout with the width values being relative to the viewport (window) width instead of the containing div.
.parent {
height: 100px;
width: 25vw;
background-color: blue;
}
.child {
width: 25vw;
transition: width 1s;
background-color: red;
height: 50px;
}
.parent:hover, .parent:hover .child {
width: 50vw;
}
<div class="parent">
<div class="child">
</div>
</div>
Related
Say we have the following set up:
.container {
background-color: red;
width: 500px;
min-height: 300px;
}
.child {
background-color: blue;
width: 500px;
height: 100%;
}
<div class="container">
<div class="child">
</div>
</div>
It's clear that the container element is rendering with a height set to 300px, but the child element has no height whatsoever, despite being set to 100%.
When the height of the container element is set to even 1px, the child element will suddenly fill the entire container with a height of 300px.
.container {
background-color: red;
width: 500px;
min-height: 300px;
height: 1px;
}
.child {
background-color: blue;
width: 500px;
height: 100%;
}
<div class="container">
<div class="child">
</div>
</div>
The container element is clearly rendering at 300px even without height being set so why does it require setting the height before the child element actually applies it's height: 100%?
Edit: To be clear, I'm not looking for a solution to having the child height take up the entire parent element, I would just like to understand why this behaves like this.
In the first case, you don't have any height defined so it's clear that the precentage height on child will fail.
From the specification:
Specifies a percentage height. The percentage is calculated with respect to the height of the generated box's containing block. If the height of the containing block is not specified explicitly (i.e., it depends on content height), and this element is not absolutely positioned, the value computes to 'auto'.
min-height is only a boundary and the height of your element still depend on its content. If you will have one that exceed 300px the element will have more than 300px
.container {
background-color: red;
width: 500px;
min-height: 300px;
padding:10px;
}
.child {
background-color: blue;
width: 500px;
height: 400px;
animation:change 2s linear infinite alternate;
}
#keyframes change{
from {
height:100px;
}
}
<div class="container">
<div class="child">
</div>
</div>
In the second case you have specified a height so the precentage will work but the height calculation is a bit tricky since we also have min-height
The following algorithm describes how the two properties influence the used value of the 'height' property:
The tentative used height is calculated (without 'min-height' and 'max-height') following the rules under "Calculating heights and margins" above.
If this tentative height is greater than 'max-height', the rules above are applied again, but this time using the value of 'max-height' as the computed value for 'height'.
If the resulting height is smaller than 'min-height', the rules above are applied again, but this time using the value of 'min-height' as the computed value for 'height'.
In the second case, it's like you explicitely defined height:300px and percentage will consider this value. In this situation, even if the content is bigger the parent element will not grow and you will have overflow. You can even define a height equal to 0.
.container {
background-color: red;
width: 500px;
min-height: 300px;
height: 0;
padding:10px;
}
.child {
background-color: blue;
width: 500px;
height: 400px;
animation:change 2s linear infinite alternate;
}
#keyframes change{
from {
height:100px;
}
}
<div class="container">
<div class="child">
</div>
</div>
Same logic will happen with max-height but in this case the height need to be very big
.container {
background-color: red;
width: 500px;
max-height: 300px;
height: 99999px;
padding:10px;
}
.child {
background-color: blue;
width: 500px;
height: 400px;
animation:change 2s linear infinite alternate;
}
#keyframes change{
from {
height:100px;
}
}
<div class="container">
<div class="child">
</div>
</div>
If you are intrested you can transform your logic using flexbox and you will be able to do what you want without having to set an explicit height.
Relying on the default stretch alignment on the cross-axis
.container {
background-color: red;
width: 500px;
min-height: 300px;
display:flex;
}
.child {
background-color: blue;
width: 500px;
/* height: 100%;*/
}
<div class="container">
<div class="child">
</div>
</div>
Or using the flex-grow property instead of height in main axis:
.container {
background-color: red;
width: 500px;
min-height: 300px;
display:flex;
flex-direction:column;
}
.child {
background-color: blue;
width: 500px;
flex-grow:0.8; /* this is 80%, use 1 for 100% */
}
<div class="container">
<div class="child">
</div>
</div>
CSS grid can also handle this
.container {
background-color: red;
width: 500px;
min-height: 300px;
display:grid;
grid-template-rows:1fr;
}
.child {
background-color: blue;
width: 500px;
height:80%;
}
<div class="container">
<div class="child">
</div>
</div>
Say we have the following set up:
.container {
background-color: red;
width: 500px;
min-height: 300px;
}
.child {
background-color: blue;
width: 500px;
height: 100%;
}
<div class="container">
<div class="child">
</div>
</div>
It's clear that the container element is rendering with a height set to 300px, but the child element has no height whatsoever, despite being set to 100%.
When the height of the container element is set to even 1px, the child element will suddenly fill the entire container with a height of 300px.
.container {
background-color: red;
width: 500px;
min-height: 300px;
height: 1px;
}
.child {
background-color: blue;
width: 500px;
height: 100%;
}
<div class="container">
<div class="child">
</div>
</div>
The container element is clearly rendering at 300px even without height being set so why does it require setting the height before the child element actually applies it's height: 100%?
Edit: To be clear, I'm not looking for a solution to having the child height take up the entire parent element, I would just like to understand why this behaves like this.
In the first case, you don't have any height defined so it's clear that the precentage height on child will fail.
From the specification:
Specifies a percentage height. The percentage is calculated with respect to the height of the generated box's containing block. If the height of the containing block is not specified explicitly (i.e., it depends on content height), and this element is not absolutely positioned, the value computes to 'auto'.
min-height is only a boundary and the height of your element still depend on its content. If you will have one that exceed 300px the element will have more than 300px
.container {
background-color: red;
width: 500px;
min-height: 300px;
padding:10px;
}
.child {
background-color: blue;
width: 500px;
height: 400px;
animation:change 2s linear infinite alternate;
}
#keyframes change{
from {
height:100px;
}
}
<div class="container">
<div class="child">
</div>
</div>
In the second case you have specified a height so the precentage will work but the height calculation is a bit tricky since we also have min-height
The following algorithm describes how the two properties influence the used value of the 'height' property:
The tentative used height is calculated (without 'min-height' and 'max-height') following the rules under "Calculating heights and margins" above.
If this tentative height is greater than 'max-height', the rules above are applied again, but this time using the value of 'max-height' as the computed value for 'height'.
If the resulting height is smaller than 'min-height', the rules above are applied again, but this time using the value of 'min-height' as the computed value for 'height'.
In the second case, it's like you explicitely defined height:300px and percentage will consider this value. In this situation, even if the content is bigger the parent element will not grow and you will have overflow. You can even define a height equal to 0.
.container {
background-color: red;
width: 500px;
min-height: 300px;
height: 0;
padding:10px;
}
.child {
background-color: blue;
width: 500px;
height: 400px;
animation:change 2s linear infinite alternate;
}
#keyframes change{
from {
height:100px;
}
}
<div class="container">
<div class="child">
</div>
</div>
Same logic will happen with max-height but in this case the height need to be very big
.container {
background-color: red;
width: 500px;
max-height: 300px;
height: 99999px;
padding:10px;
}
.child {
background-color: blue;
width: 500px;
height: 400px;
animation:change 2s linear infinite alternate;
}
#keyframes change{
from {
height:100px;
}
}
<div class="container">
<div class="child">
</div>
</div>
If you are intrested you can transform your logic using flexbox and you will be able to do what you want without having to set an explicit height.
Relying on the default stretch alignment on the cross-axis
.container {
background-color: red;
width: 500px;
min-height: 300px;
display:flex;
}
.child {
background-color: blue;
width: 500px;
/* height: 100%;*/
}
<div class="container">
<div class="child">
</div>
</div>
Or using the flex-grow property instead of height in main axis:
.container {
background-color: red;
width: 500px;
min-height: 300px;
display:flex;
flex-direction:column;
}
.child {
background-color: blue;
width: 500px;
flex-grow:0.8; /* this is 80%, use 1 for 100% */
}
<div class="container">
<div class="child">
</div>
</div>
CSS grid can also handle this
.container {
background-color: red;
width: 500px;
min-height: 300px;
display:grid;
grid-template-rows:1fr;
}
.child {
background-color: blue;
width: 500px;
height:80%;
}
<div class="container">
<div class="child">
</div>
</div>
Say we have the following set up:
.container {
background-color: red;
width: 500px;
min-height: 300px;
}
.child {
background-color: blue;
width: 500px;
height: 100%;
}
<div class="container">
<div class="child">
</div>
</div>
It's clear that the container element is rendering with a height set to 300px, but the child element has no height whatsoever, despite being set to 100%.
When the height of the container element is set to even 1px, the child element will suddenly fill the entire container with a height of 300px.
.container {
background-color: red;
width: 500px;
min-height: 300px;
height: 1px;
}
.child {
background-color: blue;
width: 500px;
height: 100%;
}
<div class="container">
<div class="child">
</div>
</div>
The container element is clearly rendering at 300px even without height being set so why does it require setting the height before the child element actually applies it's height: 100%?
Edit: To be clear, I'm not looking for a solution to having the child height take up the entire parent element, I would just like to understand why this behaves like this.
In the first case, you don't have any height defined so it's clear that the precentage height on child will fail.
From the specification:
Specifies a percentage height. The percentage is calculated with respect to the height of the generated box's containing block. If the height of the containing block is not specified explicitly (i.e., it depends on content height), and this element is not absolutely positioned, the value computes to 'auto'.
min-height is only a boundary and the height of your element still depend on its content. If you will have one that exceed 300px the element will have more than 300px
.container {
background-color: red;
width: 500px;
min-height: 300px;
padding:10px;
}
.child {
background-color: blue;
width: 500px;
height: 400px;
animation:change 2s linear infinite alternate;
}
#keyframes change{
from {
height:100px;
}
}
<div class="container">
<div class="child">
</div>
</div>
In the second case you have specified a height so the precentage will work but the height calculation is a bit tricky since we also have min-height
The following algorithm describes how the two properties influence the used value of the 'height' property:
The tentative used height is calculated (without 'min-height' and 'max-height') following the rules under "Calculating heights and margins" above.
If this tentative height is greater than 'max-height', the rules above are applied again, but this time using the value of 'max-height' as the computed value for 'height'.
If the resulting height is smaller than 'min-height', the rules above are applied again, but this time using the value of 'min-height' as the computed value for 'height'.
In the second case, it's like you explicitely defined height:300px and percentage will consider this value. In this situation, even if the content is bigger the parent element will not grow and you will have overflow. You can even define a height equal to 0.
.container {
background-color: red;
width: 500px;
min-height: 300px;
height: 0;
padding:10px;
}
.child {
background-color: blue;
width: 500px;
height: 400px;
animation:change 2s linear infinite alternate;
}
#keyframes change{
from {
height:100px;
}
}
<div class="container">
<div class="child">
</div>
</div>
Same logic will happen with max-height but in this case the height need to be very big
.container {
background-color: red;
width: 500px;
max-height: 300px;
height: 99999px;
padding:10px;
}
.child {
background-color: blue;
width: 500px;
height: 400px;
animation:change 2s linear infinite alternate;
}
#keyframes change{
from {
height:100px;
}
}
<div class="container">
<div class="child">
</div>
</div>
If you are intrested you can transform your logic using flexbox and you will be able to do what you want without having to set an explicit height.
Relying on the default stretch alignment on the cross-axis
.container {
background-color: red;
width: 500px;
min-height: 300px;
display:flex;
}
.child {
background-color: blue;
width: 500px;
/* height: 100%;*/
}
<div class="container">
<div class="child">
</div>
</div>
Or using the flex-grow property instead of height in main axis:
.container {
background-color: red;
width: 500px;
min-height: 300px;
display:flex;
flex-direction:column;
}
.child {
background-color: blue;
width: 500px;
flex-grow:0.8; /* this is 80%, use 1 for 100% */
}
<div class="container">
<div class="child">
</div>
</div>
CSS grid can also handle this
.container {
background-color: red;
width: 500px;
min-height: 300px;
display:grid;
grid-template-rows:1fr;
}
.child {
background-color: blue;
width: 500px;
height:80%;
}
<div class="container">
<div class="child">
</div>
</div>
I'm trying to increase the width of a div on hover while the height stays the same. This is tough because I get the height from padding-top: 100% which allows it to be a resizable square. So naturally as I increase the width the height organically increases too. (It is important the div height and width are equal in its normal state so it's a perfect square)
I'm now lost and unsure how to achieve this, any input is appreciated.
https://jsfiddle.net/9tc2mbwd/2/
.work-container { padding-top: 100%; }
If you don't want to set fix width and height into .work-wrapper, then..
Make the .work-container the hovered element, and do like this:
.work-wrapper {
width: 30%;
}
.work-container {
padding-top: 100%;
width: 100%;
transition: all ease 0.5s;
}
.work-container:hover {
width: 200%;
}
.work-1 {
background-color: #FEF102;
}
<div class="work-wrapper">
<div class="work-container work-1">
</div>
</div>
You can use viewport units and get rid of work-wrapper, like this:
.work-container {
width: 30vw;
height: 30vw;
transition: all ease 0.5s;
}
.work-container:hover {
width: 50vw;
}
.work-1 {
background-color: #FEF102;
}
<div class="work-container work-1">
</div>
Well, you can start off by getting rid of the percentages and adding this to " .work-wrapper":
width:150px;
height:150px;
overflow: hidden;
and keep everything the same!
Hope this helps!
For example this div is displayed:
<div class="circle"></div
.circle {
width: 300px;
height: 300px;
background: red;
border-radius: 50%;
}
but when width and height are in % it collapses:
.circle {
width: 30%;
height: 30%;
background: red;
border-radius: 50%;
}
Is there a way to get it displayed?
This is because the div has no height. width: 30%; will always make the div 30% width of the parent (<body>, in this case), which is what you want. However, height behaves a little differently.
You need to specify a 100% height for body and html like so:
html,
body {
height: 100%;
}
Working Fiddle
You can read why height: 100%; behaves like that here
You need to declare a hard width/height somewhere, in this example I put a hard width/height on a container div:
http://jsfiddle.net/exrNm/1/
<div class="con">
<div class="circle"></div
</div>
.con{
width:300px;
height:300px
}
.circle {
width: 30%;
height: 30%;
background: red;
border-radius: 50%;
}
You could easily set a hard width somewhere up the parent chain. The % needs a hard value to calculate against.