It's not the first time it happens and I have never found a good explanation.
In this particular case, I have an h3
and a p
inside a div
. As soon as I changed the p
's width
, the h3
's width changed as well, like as the width was being applied to their parent.
and
display: inline-block
to the h3
. If you remove it, you'll see that the button takes the paragraph's width of 95vw
. How come does this work?Thank you
let button = document.querySelector('.button')
let body = document.querySelector('.body')
let container = document.querySelector('.container')
button.addEventListener('click', ()=> {
let colorOne = parseInt((Math.random() * 255) + 1)
let colorTwo = parseInt((Math.random() * 255) + 1)
let colorThree = parseInt((Math.random() * 255) + 1)
let colorOneOne = parseInt((Math.random() * 255) + 1)
let colorTwoTwo = parseInt((Math.random() * 255) + 1)
let colorThreeThree = parseInt((Math.random() * 255) + 1)
let deg = parseInt((Math.random() * 360) + 1)
body.style.background = 'linear-gradient(' + deg + 'deg' + ', ' + 'rgb(' + colorOne + ', ' + colorTwo + ', ' + colorThree + ')' + ',' + 'rgb(' + colorOneOne + ',' + colorTwoTwo + ',' + colorThreeThree + '))'
//linear-gradient(45deg, rgb(28,28,84), rgb(38,58,119))
document.querySelector('.color').innerText = 'linear-gradient(' + deg + 'deg' + ', ' + 'rgb(' + colorOne + ', ' + colorTwo + ', ' + colorThree + ')' + ',' + 'rgb(' + colorOneOne + ',' + colorTwoTwo + ',' + colorThreeThree + '))'
button.style.border = 'none'
document.querySelector('.scrollto').style.display = 'block'
})
window.addEventListener('touchmove', ()=> {
body.style.background = 'white'
document.querySelector('.color').innerText = ''
document.querySelector('.scrollto').style.display = 'none'
button.style.border = '1px solid black'
})
.button {
font-family: 'Poppins', sans-serif;
border-radius: .5em;
padding: .3em .7em;
font-size: 1.1em;
position: relative;
background: white;
mix-blend-mode: screen;
border: 1px solid black;
display: inline-block;
}
@media screen and (max-width: 382px) {
.button {
width: 10em;
}
}
body {
min-height: 100vh;
margin: 0;
}
.color {
font-family: 'Poppins', sans-serif;
color: white;
text-shadow: 1px 1px 3px black;
letter-spacing: 1px;
display: block;
width: 95vw;
border: 2px solid black;
}
.container {
text-align: center;
position: absolute;
top: 40vh;
left: 50vw;
transform: translate(-50%, -50%);
}
.scrollto {
position: absolute;
bottom: 10px;
left: 50vw;
transform: translateX(-50%);
font-family: 'Poppins', sans-serif;
font-size: .7em;
display: none;
}
<body class="body">
<div class="container">
<h3 class="button">Generate Gradient</h3>
<p class="color"></p>
</div>
<div class="line">
<p class="scrollto">swipe on screen to reset</p>
</div>
If you remove the inline-block
from h3
it will get its default display which is block
and this means take full width of the parent element.
Now, the trick is the width of the parent element that is a position:absolute
one. Its width is defined by the shrink-to-fit algorithm which means that the width is based on its content.
The content is a h3
block element and a p
block element. You defined only the width of p
so this will define the width of the position:absolute
element and then the h3 will be full width of its parent element so it will logically follow the width set to p
.
Here an illustration of different cases to better understand:
.container {
position:absolute;
border:1px solid;
}
.container > * {
border:1px solid red;
}
<div class="container">
<h3 class="button">Generate Gradient</h3>
<p class="color">some text </p>
</div>
<div class="container" style="top:150px">
<h3 class="button">Generate Gradient</h3>
<p class="color">a text longer than the above one</p>
</div>
<div class="container" style="left:250px">
<h3 class="button" style="display:inline-block">Generate Gradient</h3>
<p class="color">a text longer than the above one</p>
</div>
You can see that by default both should be 100% of the parent width and the longer content will define that width. If you make one element inline-block
it will simply fit its content and will no more obey to the block elements rule which is to be 100% width of the parent.
This is a simplified explanation, if you want more accurate detail you need to refer to the specification and find how the width is calculated in each case.
Block elements: https://www.w3.org/TR/CSS21/visudet.html#blockwidth
Inline block elements: https://www.w3.org/TR/CSS21/visudet.html#inlineblock-width
Absolutely positioned elements: https://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width