Fixed position inside absolute inside fixed - html

One DOM element with position: fixed, another one inside with css-transforms, another one inside that one with position: fixed
All fixed position elements is supposed to be positioned based on the viewport as container, but when the middle element has css-transforms, the inner fixed element is positioned based on the middle element instead of the viewport.
.backdrop {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.1);
}
.contents {
position: absolute;
top: 50%;
left: 50%;
width: 300px;
height: 200px;
border: 1px solid red;
transform: translateX(-50%) translateY(-50%);
}
.inner-fixed {
position: fixed;
top: 20px;
left: 20px;
background: rgba(0, 0, 255, 0.1);
width: 100px;
height: 50px;
}
<div class="backdrop">
<div class="contents">
Contents in centered box
<div class="inner-fixed">
Inner-fixed contents
</div>
</div>
</div>
If I remove the transform on the .contents, the inner element is fixed based on viewport.
Happens in Chrome 62 and Firefox 57 (Mac)
Any way around this with the same DOM, so the inner element is fixed based on the viewport without having to skip the use of css-transforms?
With the css-transform:
Without the css-transform:

Related

How to lay out with z-index positioned elements in a third level hierarchy

I have a problem with z-index property. I have some absoluted positioned elements (div in the code)one inside each other. The first div inside (red div) naturally would be in front of its parent (aliceblue element), thus I give a negative z-index to the red div inside and it's ok. But the aqua div (inside the red div) is in front of red element too (instead I would lay out the aqua element behind the red element), to lay out it behind I give it z-index:-5 for example but it doesn't work because I created a new stacking context different from stacking context of its father
div {
width: 300px;
height: 300px;
text-align: center;
position: absolute;
}
.a {
background-color: aliceblue;
position: relative;
}
.a1 {
background-color: red;
left: 20px;
top: 20px;
z-index: -1;
}
.a11 {
background-color: aqua;
left: 10px;
top: 10px;
/* z-index: -5; This doesn't work*/
}
.a2 {
background-color: yellow;
top: 40px;
z-index: -2;
}
<div class="a">
A
<div class="a1">
A1
<div class="a11">A11</div>
</div>
<div class="a2">A2</div>
</div>
So far we haven't found a way to do this using z-index.
The following method may or may not be suitable for your particular use case/overall context but it does solve the problem for the code given in the question.
This snippet uses 3d transforms rather than z-index to position the elements in relation to the viewer who is looking head on to the screen.
Of course we don't actually want to introduce perceptible perspective so the snippet uses a small shift back (0.1px). This seems enough to get the system to position elements on top of each other in the required order but small fractions were ignored (at least on my Windows10 Edge).
div {
width: 300px;
height: 300px;
text-align: center;
position: absolute;
transform-style: preserve-3d;
}
.a {
background-color: aliceblue;
position: relative;
transform: translate3d(0, 0, 0);
}
.a1 {
background-color: red;
left: 20px;
top: 20px;
transform: translate3d(0, 0, -0.1px);
}
.a11 {
background-color: aqua;
left: 10px;
top: 10px;
transform: translate3d(0, 0, -0.2px);
}
.a2 {
background-color: yellow;
top: 40px;
transform: translate3d(0, 0, -0.4px);
}
<div class="a">
A
<div class="a1">
A1
<div class="a11">A11</div>
</div>
<div class="a2">A2</div>
</div>

Align DIV container to bottom of page with variable height element in it

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.
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>

Scaling down group of CSS shapes

I'm trying to make a group of elements sit in the upper left corner on a webpage. When the browser is at its max, the elements look fine. But when the browser width becomes less than the biggest element's width (outer-circle of 927px), the horizontal scrollbar appears. I would like to make it so that the elements scale down and that the horizontal scrollbar doesn't appear. I could resize all of the individual elements with media queries but I wanted to know if there's a better way of doing it.
I tried inserting the group into a bootstrap column and that didn't do anything. I also tried setting the element sizes to vw (example is setting .inner-circle width and height to 20vw). That worked until I started resizing the browser and the elements shifted off of the page.
HTML:
<div class="corner">
<div class="moon"></div>
<div class="inner-circle"></div>
<div class="mid-circle"></div>
<div class="outer-circle"></div>
</div>
CSS:
.moon{
position: absolute;
width: 240px;
height: 240px;
left: 170px;
top: -40px;
border-radius: 50%;
box-shadow: -80px 50px white;
}
.inner-circle {
position: absolute;
width: 635px;
height: 598px;
left: -134px;
top: -300px;
border-radius: 50%;
background:rgba(229, 227, 238, 0.5);
opacity: 0.4;
}
.mid-circle {
position: absolute;
width: 841px;
height: 795px;
left: -240px;
top: -400px;
border-radius: 50%;
background: rgba(229, 227, 238, 0.5);
opacity: 0.3;
}
.outer-circle {
position: absolute;
width: 927px;
height: 902px;
left: -230px;
top: -410px;
border-radius: 50%;
background: rgba(229, 227, 238, 0.5);
opacity: 0.2;
}
You have given the values in px. Better give in perecentages, so that it will adjust with respect to the screen.
Or try giving position relative to the parent div 'corner'.
Try using the following css properties:
max-width: (your width)px;
width: 100%;
This will decrease the size of your div as your screen size starts to get smaller than the set width.

How to create a tutorial overlay feature in a website?

I want to create a tutorial feature for my user on my website. I'm planning to create a dark overlay layer on the whole screen, and on a specific area, the background is completely transparent, so the user understand the area which the tutorial is talking about.
Here what I have done :
<body>
<div>
<p>THIS IS CONTENT</p>
</div>
<div class="overlay">
<div></div>
</div>
</body>
on CSS :
.overlay {
background: rgba(0, 0, 0, 0.5);
position: fixed;
top:0;
left: 0;
width: 100%;
height: 100%;
z-index: 9999;
}
.overlay > div {
background: rgba(0, 0, 0, 0);
width: 100%;
position: absolute;
height: 30px;
top:0;
left: 0;
}
the div inside .overlay has no effect since the background of the div is ON TOP of the .overlay
What I think prevents your content div from being displayed under the overlay is that you haven't specified a z-index for that. If you specify one for the larger container div like so: <div id="cont"> and give it a z-index smaller than that of the overlay (<9999) perhaps your problem will be solved.
UPDATE: I've read through your question again, and to solve your actual problem, you should make specific content and background div-s inside the master overlay container. It also seems to be important to add position: absolute; to the content div of the overlay.
UPDATE 2: To make the #cont stay visible as the overlay shows up, just add a greater z-index for that div than the one used by the overlay, and add a position: absolute; to it to make it specific.
Below is a working snippet.
#cont {
position: absolute;
z-index: 9999;
color: blue;
}
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 9990;
}
#overlay-cont {
color: red;
position: absolute;
top :40px;
left: 50px;
z-index: 9990;
display: block;
}
#overlay-bg {
background: rgba(0, 0, 0, 0.5);
height: 100%;
Width: 100%;
position: fixed;
top: 0px;
left: 0px;
z-index: 9980;
}
<body>
<div id="cont">
<p>THIS IS CONTENT</p>
</div>
<div class="overlay">
<div id="overlay-cont">The overlay content goes here.</div>
<div id="overlay-bg"></div>
</div>
</body>

Why does a child div's box shadow sometimes jump to the parent div?

I'm trying to animate a box shadow transition with the aid of CSS pseudo-elements :before and :after. In principle, the code provided in the JSFiddle works fine, except that on mousing out of the subdiv in the lefthand column, its box shadow jumps to the leftparentdiv. This behavior occurs whenever the window is window is small enough that overflow-y: scroll kicks in. The problem seems to occur in all browsers that support box shadows.
I guess I'm missing something obvious here, but can't figure out what.
body {
background-color: pink;
}
.subdiv {
width: 25vw;
border: 1px solid;
}
.subdiv:after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.30);
transition: all 0.6s ease-in-out;
opacity: 0;
}
.subdiv:hover {
transform: scale(1.1, 1.1);
}
.subdiv:hover:after {
opacity: 1;
}
#leftparentdiv {
position: absolute;
left: 0;
top: 0;
border: 1px solid;
width: 47vw;
padding: 3%;
overflow-y: scroll;
}
#rightparentdiv {
position: absolute;
left: 53vw;
top: 0;
border: 1px solid;
width: 47vw;
padding: 3%;
overflow-y: scroll;
}
<div id="leftparentdiv">
<div class="subdiv">
Blabla;
</div>
</div>
<div id="rightparentdiv">
<div class="subdiv">
Blabla;
</div>
</div>
JSFiddle
You have a transform on .subdiv:hover, but none on .subdiv. A box with a transform establishes a containing block. This is what allows the pseudo-element (and its shadow) to be painted around .subdiv when the mouse is over it. But when the mouse leaves the element, the pseudo-element (and its shadow) jumps to .subdiv's parent because .subdiv no longer establishes a containing block, so the pseudo-element sizes according to the parent element and not its originating .subdiv because the parent element does establish a containing block. This is also true when the layout is first rendered, before the cursor ever touches the .subdiv (you just don't see it because the pseudo-element is invisible).
This behavior actually occurs only when .subdiv's parent has overflow: visible. It doesn't occur otherwise. The reason for that is because the pseudo-element's box shadow is actually overflowing the parent element whenever its originating .subdiv is not :hover. So a non-visible overflow clips the shadow away. This isn't immediately apparent because the parent element doesn't scroll — and the reason for that is because box shadows don't affect layout.
Assuming the desired behavior is for .subdiv to always be the one casting the shadow, all you have to do is position .subdiv so it establishes a containing block at all times:
body {
background-color: pink;
}
.subdiv {
width: 25vw;
position: relative;
border: 1px solid;
}
.subdiv:after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.30);
transition: all 0.6s ease-in-out;
opacity: 0;
}
.subdiv:hover {
transform: scale(1.1, 1.1);
}
.subdiv:hover:after {
opacity: 1;
}
#leftparentdiv {
position: absolute;
left: 0;
top: 0;
border: 1px solid;
width: 47vw;
padding: 3%;
overflow-y: scroll;
}
#rightparentdiv {
position: absolute;
left: 53vw;
top: 0;
border: 1px solid;
width: 47vw;
padding: 3%;
overflow-y: scroll;
}
<div id="leftparentdiv">
<div class="subdiv">
Blabla;
</div>
</div>
<div id="rightparentdiv">
<div class="subdiv">
Blabla;
</div>
</div>