Reputation: 411
I am trying to position an element on a page so that it is always spaced away from other control elements on the page. I want this element to be positioned anywhere on the page, depending on other control elements on the page, what action the user has taken etc. These are the eight valid positions:
TOP_CENTER
TOP_LEFT
TOP_RIGHT
LEFT_CENTER
RIGHT_CENTER
BOTTOM_CENTER
BOTTOM_LEFT
BOTTOM_RIGHT
What I have so far are 3 component elements: 1) a DIV container, 2) an image which should always be at the top of the DIV container, 3) some text which should always be at the bottom of the DIV container. My CSS looks as follows:
#floatingElement {
left: 60px;
top: 11%;
width: 25%;
height: 25%;
position: absolute;
pointer-events: none;
z-index: 1;
}
#floatingElement img {
display: block;
margin: auto;
max-width: 95%;
max-height: 100%;
}
#floatingElement div {
text-align: center;
background: rgba(255,255,255,0.5);
border-radius: 5%;
box-shadow: 3px 3px 2px #888888;
font-size: 2vmax;
}
The above works perfectly whenever the element is positioned "TOP" or "CENTER". However, "BOTTOM" positioning is causing problems, I think because the container DIV is somehow not taking into account its height based on the amount of text in the 3rd (text DIV) element.
How can I make it so that the element can always align to the bottom of the page whenever a "BOTTOM" position is chosen, so that the container DIV includes the height of the text DIV (which can vary depending on the amount of text in that DIV), similar to this image:
The black border is my window, the red box is my image and the green box is the text DIV. Both the red and green boxes are inside my container DIV.
Upvotes: 1
Views: 402
Reputation: 7433
Upon being altered using bottom
, the scenario you want is not working as expected because you specified the height
of #floatingElement
to be fixed (in your case, 25%). Having a fixed value relative to the container and not considering the height of the text div, the floating element's position will definitely seem off when altered using bottom
. This is because bottom
places the element based on the bottom-most pixel of your element's height, which in your case may be smaller than enough to cover your whole text div's and image's height. To see what I mean, do try removing the comment on height below and inspect the element of #floatingElement
.
Here's a working example, simply click the button to adjust the div's position (try using full-page mode when running as the window is a tad small).
const button = document.querySelector('.adjustPosition')
const addText = document.querySelector('.addText')
const elem = document.querySelector('#floatingElement')
const textDiv = elem.querySelector('.textDiv')
button.addEventListener('click', e => {
if (elem.classList.contains('topLeft')) {
elem.classList.add('topCenter')
elem.classList.remove('topLeft')
} else if (elem.classList.contains('topCenter')) {
elem.classList.add('topRight')
elem.classList.remove('topCenter')
} else if (elem.classList.contains('topRight')) {
elem.classList.add('rightCenter')
elem.classList.remove('topRight')
} else if (elem.classList.contains('rightCenter')) {
elem.classList.add('bottomRight')
elem.classList.remove('rightCenter')
} else if (elem.classList.contains('bottomRight')) {
elem.classList.add('bottomCenter')
elem.classList.remove('bottomRight')
} else if (elem.classList.contains('bottomCenter')) {
elem.classList.add('bottomLeft')
elem.classList.remove('bottomCenter')
} else if (elem.classList.contains('bottomLeft')) {
elem.classList.add('leftCenter')
elem.classList.remove('bottomLeft')
} else if (elem.classList.contains('leftCenter')) {
elem.classList.add('topLeft')
elem.classList.remove('leftCenter')
}
})
addText.onclick = () => {
textDiv.innerText += "Added some more text so that the div can be larger"
}
html,
body {
height: 100%;
width: 100%;
margin: 0;
}
#floatingElement {
width: 25%;
/* height: 25%; This causes the height to be fixed */
position: absolute;
pointer-events: none;
z-index: 1;
}
#floatingElement img {
display: block;
width: 100%;
height: 100px;
margin: auto;
object-fit: cover;
}
#floatingElement .textDiv {
text-align: center;
background: rgba(255, 255, 255, 0.5);
border-radius: 5%;
box-shadow: 3px 3px 2px #888888;
}
.adjustPosition {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 25px;
height: 25px;
background: #12121299;
border-radius: 50%;
cursor: pointer;
}
.addText {
position: absolute;
top: 60%;
left: 50%;
transform: translate(-50%, -50%);
cursor: pointer;
}
.topLeft {
top: 10px;
left: 10px;
}
.topCenter {
top: 10px;
left: 50%;
transform: translateX(-50%);
}
.topRight {
top: 10px;
right: 10px;
}
.leftCenter {
top: 50%;
left: 10px;
transform: translateY(-50%);
}
.rightCenter {
top: 50%;
right: 10px;
transform: translateY(-50%);
}
.bottomLeft {
bottom: 10px;
left: 10px;
}
.bottomRight {
bottom: 10px;
right: 10px;
}
.bottomCenter {
bottom: 10px;
left: 50%;
transform: translateX(-50%);
}
<div id="floatingElement" class="topLeft">
<img src="https://homepages.cae.wisc.edu/~ece533/images/airplane.png">
<div class="textDiv">Variable height here because it has a long text</div>
</div>
<div class="adjustPosition"></div>
<div class="addText">Add Text</div>
Upvotes: 2