Fixed block with same width of its parent
Show and explain how create a fixes block that will maintain its parent width.
HTML
<div class="container">
<header>
<h1>Fixed block with same width of its parent</h1>
</header>
<main>
<article>
<h2>Fixed blocks, how control them?</h2>
<p>Create the desired behavior with CSS sometimes is kind of tricky, once a while the output seems buggy, but most of times are just something that nobody remember. Now lets see one of tricky cases in fixed blocks and explain why this "strange" behavior and how make it right.</p>
<p>Occasionally, a block is needed to float on the screen, piece of cake uh? Create a <div>, specify its width and height, its position on the screen and done, but... if this block needs to fit somewhere in your layout? How specify its width? Simple, create a wrapper that will be a fixed block and set width: inherit, this works, but only if its parent has a width absolute value or its parent has same same of window.</p>
<p>Nowadays, layout needs to be responsive and usually has a container element that specify max-width of your page and most of your layout have width as percentage to adequate every screen size, taking the previous solution will not work, because if you set width: inherit to fixed element, it will get exactly same width value of its parent element, in this case a percentage value, now a tricky behavior comes out, parent's element of fixed block will use its parent size to calculate its own size, but the fixed block, for size calculations, <span class="bold">window</span> size will be used, then you will get a percentage of window size, and you always get more than you need.</p>
<p>" - Ahhhhh, and now, what should I do?"</p>
<p>Easy, specify its max-width.</p>
<p>" - Uhg? How this will work? And how I find this value?"</p>
<p>One question, in this particular case (using width: inherit), when fixed block is bigger than its parent element? Answer: Just when window size is bigger than your container element. Said that, is easy to figure out the correct max-width value, get max-width...
CSS
/* 1 - Just adding basic layout for this example */
body {
margin: 8px 0;
/*Style*/
background-color: #2D2A32;
color: #2D2A32;
text-align: center;
font-family: "Century Gothic", CenturyGothic, Geneva, AppleGothic, sans-serif;
}
.bold {
font-weight: bold;
}
.container {
position: relative;
max-width: 800px;
margin: 0 auto;
/*Style*/
background-color: #5092AA;
border-radius: 5px;
}
.container::after {
/*Clearfix*/
clear: both;
content: "";
display: table;
}
header {
width: 100%;
/* Hack to include child margin */
border: 1px solid transparent;
}
main {
float: left;
width: 65%;
/*Style*/
background-color: #C5EDAC;
border-radius: 5px;
}
article {
padding-left: 1em;
padding-right: 1em;
}
article p {
/*Style*/
text-align: justify;
line-height: 1.5em;
text-indent: 16px;
}
aside {
float: left;
margin-left: 5%;
width: 30%;
}
footer {
width: 100%;
/* height: 80px; */
clear: both;
/* Hack to include child margin */
border: 1px solid transparent;
/*Style*/
text-align: center;
}
/**********************************/
/* 2 - Fixed block related styles */
.related_wrapper {
/* Use for style this element */
background-color: #C5EDAC;
border-radius: 5px;
/* Hack to include child margin */
border: 1px solid transparent;
}
.related_wrapper.fixed {
position: fixed;
top: 0;
width: inherit;
/*IMPORTANT property, explained in article*/
max-width: 238px; /* Math: (800px x 30%) - 2px */
/* 800px from .container max-width */
/* 30% from fixed block container */
/* 2px from border used in .related_wrapper */
/*Style just to see when get fixed class*/
background-color: #99C2A2;
}
JavaScript
/*Everything here load after DOM is loaded*/
/* Simple script to sticky a div, maybe not too simple,
* because efficience is always a concern.
*/
var relatedFixedDiv = {
'element': document.getElementById('js-related_content'),
'position': 91,
'class': 'fixed'
};
var lastYPos = 0;
var lock = false;
function didScroll(obj) {
if(lastYPos > obj.position) {
obj.element.classList.add(obj.class);
}
if(lastYPos < obj.position) {
obj.element.classList.remove(obj.class);
}
lock = false;
}
window.addEventListener('scroll', function(e){
if (!lock) {
lastYPos = window.pageYOffset;
window.requestAnimationFrame(function() {
didScroll(relatedFixedDiv);
});
lock = true;
}
}, false);