Keep element with a percentage as a position fixed


Keep element with a percentage as a position fixed



I have a container of variable height, and would like to put an element at the middle of it. So I've set these styles:


#parent {
position: relative;
}

#child {
position: absolute;

top: 50%;
transform: translateY(-50%);
}



Which work in most cases. However, the container's height is not only variable, but it also changes constantly.
Because of this, that code won't work. An example:




@keyframes changeSize {
0% {
height: 100px;
}

50% {
height: 150px;
}

100% {
height: 100px;
}
}


#parent {
position: relative;
width: 400px;
height: 300px;
background: red;

animation-name: changeSize;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
}

#child {
position: absolute;
margin-block-start: 0;
margin-block-end: 0;
right: 0;
top: 50%;
transform: translateY(-50%);
}


<div id="parent">
<p id="child">I should not be moving...</p>
</div>



As you can see, it's moving. So, my question is, is there a way to place it in the middle of the element (vertically) but without having it move if the container changes size - just with CSS?





The only way I see to resolve this is a JavaScript solution. Percentage units on #child are relative to the containing element. Since the height of the containing element is changing, you are noticing the unit change. You need to use fixed units (like pixels). The only way to get an initial 50% reading in pixels is with JavaScript. Writing an answer now...
– www139
Jun 30 at 18:50






if the height is fixed intially the why not simply use it to define the top value ?
– Temani Afif
Jun 30 at 19:28




1 Answer
1



The issue is that percentage measure units are relative to the containing element. Since the #parent is changing in height through the animation, the value of a percentage unit changes. The unit change affects the percentage height property applied to the #child. The work-around might be some very complicated CSS (might not work in every situation) so the best solution is to use JavaScript to capture the initial 50% height in pixels so the unit no longer changes. It is important to also use a resize event listener to apply a new 50% height should the browser window be resized.


resize




window.addEventListener('load',resizeDiv());
window.addEventListener('resize',resizeDiv());

function resizeDiv(){
var initialHeight = document.getElementById('parent').offsetHeight/2;
document.getElementById('child').style.top = initialHeight+'px';
}


@keyframes changeSize {
0% {
height: 100px;
}

50% {
height: 150px;
}

100% {
height: 100px;
}
}


#parent {
position: relative;
width: 400px;
height: 300px;
background: red;

animation-name: changeSize;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
}

#child {
position: absolute;
margin-block-start: 0;
margin-block-end: 0;
right: 0;
}


<div id="parent">
<p id="child">Hey!! I'm not moving anymore!</p>
</div>






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

List of Kim Possible characters

Audio Livestreaming with Python & Flask

NSwag: Generate C# Client from multiple Versions of an API