CSS Overlay not allowing DIv on top [duplicate] - javascript

I want the div1 to be above div2. I try with z-index but it does not work.
I've tried this code:
div {
width: 100px;
height: 100px;
}
.div1 {
background: red;
z-index: 1;
}
.div2 {
background: blue;
margin-top: -15vh;
z-index: 2
}
<div class="div1"></div>
<div class="div2"></div>

You can add position: relative to both divs and create stacking context
div {
width:100px;
height: 100px;
}
.div1 {
background: red;
z-index: 2;
position: relative;
}
.div2 {
background: blue;
margin-top: -15vh;
z-index: 1;
position: relative;
}
<div class="div1"></div>
<div class="div2"></div>
Or you could use transform-style: preserve-3d; so now .div1 should be positioned in the 3D-space and not flattened in the plane.
div {
width:100px;
height: 100px;
}
.div1 {
background: red;
z-index: 2;
transform-style: preserve-3d;
}
.div2 {
background: blue;
margin-top: -15vh;
z-index: 1;
}
<div class="div1"></div>
<div class="div2"></div>
You can also use some random transform like translate or rotate
div {
width:100px;
height: 100px;
}
.div1 {
background: red;
z-index: 2;
transform: translate(1px);
}
.div2 {
background: blue;
transform: translate(1px, -15vh);
z-index: 1;
}
<div class="div1"></div>
<div class="div2"></div>
Filters also work but they have bad Support
div {
width:100px;
height: 100px;
}
.div1 {
background: red;
filter: brightness(0.4);
z-index: 2;
}
.div2 {
background: blue;
margin-top: -15vh;
filter: brightness(0.4);
z-index: 1;
}
<div class="div1"></div>
<div class="div2"></div>

In many cases an element must be positioned for z-index to work.
Indeed, applying position: relative to the divs in the question would solve the z-index problem.
Actually, position: fixed, position: absolute and position: sticky will also enable z-index, but those values also change the layout. With position: relative the layout isn't disturbed.
Essentially, as long as the element isn't position: static (the default value) it is considered positioned and z-index will work.
Some answers here and in related questions assert that z-index works only on positioned elements. As of CSS3, this is no longer true.
Elements that are flex items or grid items can use z-index even when position is static.
From the specs:
4.3. Flex Item Z-Ordering
Flex items paint exactly the same as inline blocks, except that order-modified document order is used in place of raw
document order, and z-index values other than auto create a stacking context even if position is static.
5.4. Z-axis Ordering: the z-index property
The painting order of grid items is exactly the same as inline blocks, except that order-modified document order is
used in place of raw document order, and z-index values other than auto create a stacking context even if
position is static.
Here's a demonstration of z-index working on non-positioned flex items: https://jsfiddle.net/m0wddwxs/

z-index only applies to elements with a position other than static, so for example: relative, absolute, or fixed.
div {
width:100px;
height: 100px;
position:relative;
}
.div1 {
background: red;
z-index: 2;
}
.div2 {
background: blue;
margin-top: -15vh;
z-index: 1
}
<div class="div1"></div>
<div class="div2"></div>

The default property for div is position:static, Add position:relative in both the div then only z-index will work.

Related

Is there a way to mask a sticky element using an absolute element?

I've been trying to create a sticky position image that changes as it scrolls across the border between two sections of my page. So basically, there should be two sticky position images, the top one gets masked by the bottom section and the bottom gets masked by the top section. I am having trouble figuring out a way to mask both images at the same time (you can use the bottom section div to hide the top image, and vice versa, but not both at the same time).
Here's an image to illustrate what I'm trying to do
Here's the code I'm using:
.lblue {
height: 40vh;
width:10vw;
position: -webkit-sticky;
position: sticky;
top:30vh;
left:45vw;
background:lightblue;
}
.lred {
height: 40vh;
width:10vw;
position: -webkit-sticky;
position: sticky;
top:30vh;
left:45vw;
background:lightcoral;
}
.blue {
position: absolute;
top:0;
height:150vh;
width:100vw;
background:blue;
}
.red {
position: absolute;
top:100vh;
height:100vh;
width: 100vw;
background:red;
}
<div class="blue">
<div class="lblue"></div>
</div>
<div class="red">
<div class="lred"></div>
</div>
Thank you!
Here’s a solution. The trick is to use the images as CSS backgrounds, because CSS backgrounds can be easily fixed in the viewport of their parents.
.blue {
position: absolute;
top:0;
height:150vh;
width:100vw;
background: blue fixed linear-gradient(lightblue, lightblue) 45vw 30vh / 10vw 40vh no-repeat;
}
.red {
position: absolute;
top:100vh;
height:100vh;
width: 100vw;
background: red fixed linear-gradient(lightcoral, lightcoral) 45vw 30vh / 10vw 40vh no-repeat;
}
<div class="blue"></div>
<div class="red"></div>
In this solution, you can replace linear-gradient(color, color) by the URL of your image, using url(https://…). I used gradients because, for the browser, gradients are (generated) images. So, this trick actually works with images.
The position: absolute also becomes useless, at least for the demo.
The long background rule may need some explanations. background is a shorthand (= a short way to write several properties in a single line) for:
background-color: red;
background-attachement: fixed;
background-image: linear-gradient(lightcoral, lightcoral);
background-position: 45vw 30vh;
background-size: 10vw 40vh;
background-repeat: no-repeat;
position:fixed can do this if you conside a clip-path trick to hide the overflow so that each element will show only inside its section
.lblue,
.lred {
height: 40vh;
width: 10vw;
position: fixed;
top: 30vh;
left: 45vw;
background: lightblue;
}
.lred {
background: lightcoral;
}
.blue,
.red {
height: 100vh;
background: blue;
clip-path: inset(0 0 0 0); /* this is important */
}
.red {
background: red;
}
body {
margin: 0
}
<div class="blue">
<div class="lblue"></div>
</div>
<div class="red">
<div class="lred"></div>
</div>

How to change value of CSS pseudoelement property using JavaScript in scrollspy?

I'm looking for a relatively simple and standard way of changing CSS pseudoelement property value by JS Scrollspy.
The parent element (section of a landpage) should change grayscale, while scrolled, and its child should have position:fixed.
As it turns out, it's impossible to make it in an easy way, because any filter is removing position:fixed by definition. More about this: CSS-Filter on parent breaks child positioning
Moving that background-image to a pseudoelement creates another problem: manipulation of the pseudoelement's properties by JS.
The expected result: I wanted to make a section of a landing page, having grayscale filter for background image. That's the easy part. But it should has less grayscale, while moving upward (the more picture user see, the more color it has), and centered content element shuffles up from previous section, and later hiding under next one.
So basically I need two things:
filter grayscaled background image, with dynamically changing value of a grayscale, relative to distance to the top of the window (JS scrollspy)
position:fixed central content element visible only in that section
Illustration (with background-picture in pseudoelement) is here: https://codepen.io/tdudkowski/pen/MLyMyG
HTML
<section class="one">
</section>
<section class="two">
<div><p>DIV with a position:fixed</p></div>
</section>
<section class="three"></section>
CSS
section {
position: relative;
max-width: 1000px;
height: 70vh;
background-color: #eee;
margin: 0 auto;
overflow: hidden;
}
.two {
background-color: transparent;
/* Try to uncomment rule below */
/* filter: grayscale(50%); */
}
.two div {
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 30rem;
height: 10rem;
background-color: #f00;
z-index: 1;
}
.one,
.three {
z-index: 100;
}
/* background of section */
section.two::after {
content: "";
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-image: url(https://picsum.photos/1000/200);
background-size: cover;
background-repeat: no-repeat;
z-index: -1;
/* filter: grayscale(50%); */
}

Stack customized windows(divs) using CSS

I'm doing a single page application where you're suppose to be able to open multiple customized windows on the page(not browser tabs/windows, but windows created with DOM). I want the windows to stack on top of each-other with a certain XY-offset. I've tried added a transform: translate(5%, 5%)to the divs after the first div, but it simply isn't working.
I want them to stack like this:
But right now, they´re just stacking on top of each other.
HTML:
<main>
<div class=window><div class=app></div></div>
<div class=window><div class=app></div></div>
<div class=window><div class=app></div></div>
</main>
CSS:
main {
transition: margin-left .5s;
padding: 20px;
position: fixed;
margin-left: 100px;
width: 100%;
height: 100%;
top: 0;
}
.window {
z-index: 1;
left: 0;
top: 0;
width: 250px;
height: 400px;
}
Any ideas?
Try adding position: absolute to all the divs and use left: <num>px and top: <num>px to position them. Make sure the containing element is position: relative, otherwise the divs will be absolutely positioned relative to the "viewport".
See this article for more on absolute positioning.
Ok, this works with some caveats: http://codepen.io/anon/pen/dNbqgE
html:
<div class="card">1</div>
<div class="card">2</div>
<div class="card">3</div>
<div class="card">4</div>
<div class="card">5</div>
css:
.card {
width: 100px;
height: 200px;
outline: 1px solid #cc0000;
position: absolute;
background: #ddd;
}
.card:nth-of-type(n + 1) {
transform: translate(5%, 5%);
}
.card:nth-of-type(n + 2) {
transform: translate(10%, 10%);
}
.card:nth-of-type(n + 3) {
transform: translate(15%, 15%);
}
.card:nth-of-type(n + 4) {
transform: translate(20%, 20%);
}
.card:nth-of-type(n + 5) {
transform: translate(25%, 25%);
}
The caveat is that you have to define a new nth-of-type rule for each level of card you need. If you're using less, sass, or other css build tool you can pretty easily setup a macro to generate any number of these.
transform: translate(...) applies to the element itself, not to the parent, so maybe that's the case it doesn't work for you. I would use a similar approach like the one mentioned by Jason Cemra. Check out this another answer, maybe it helps you: How to use transform:translateX to move a child element horizontally 100% across the parent
to position of window div's, we have to set x-y position relative to a known reference. if all win div's are in a same parent, we have use different offset for them: eg: transform: translate(5%, 5%); for first div, transform: translate(10%, 10%); for second div, and so on.
another way is to nest them in each other such that the same value of offset can be used for all divs, but as their parent have different position, they get desired position:
<html>
<head>
<style type="text/css">
#main {
transition: margin-left .5s;
padding: 20px;
position: fixed;
margin-left: 100px;
width: 800px;
height: 500px;
top: 0;
}
.window {
position:absolute;
z-index: 1;
left: 0;
top: 0;
width: 250px;
height: 400px;
border:1px solid navy;
transform: translate(5%, 5%); /* this is relative to current position */
}
</style>
</head>
<body>
<div id=main>
<div class=window><div class=app>w1</div>
<div class=window><div class=app>w2</div>
<div class=window><div class=app>w3</div>
</div>
</div>
</div>
</div>
</body>
</html>

Make <div> scale to content when absolutely positioned?

Usually a <div> will expand to fill content insize.
<div>
<p>Hello</p>
</div>
The <div> scales to contain the <p>
Is it possible to make the <div> do this when it's absolutely positioned?
In my case I have a modal which has a set height and width, but I want to make it scale to the content.
Something like this? http://jsfiddle.net/3L99pycm/
CSS:
div {
position: absolute;
left: 50%;
top: 100px;
background-color: red;
width: 30%;
height: 100px;
}
p {
background-color: blue;
color: white;
}
div behave the same independently from its position, most likely the problem is that you are setting a fixed size parameter somewhere.
Well You dont need to do anything special to make the absolute div scale to the child. I added an example here http://jsfiddle.net/rtkvswmn/
CSS
div {
position: absolute;
background: red;
}
p{
width: 100px;
background: blue;
text-align: center;
}

How to overlay "transformed" element?

HTML structure:
<div class="menu">
menu
<div class="submenu">submenu</div>
</div>
<div class="video">video</div>
The question is how to show the .submenu element on top of the .video element which has transform css rule without changing the structure?
Fiddle - http://jsfiddle.net/vpetrychuk/YtAP6/1/
Update: .menu is also transformed.
You can set the z-index to a positive number large enough:
.submenu {
background: #c00;
position: absolute;
top: 0; left: 40px;
height: 100px;
z-index:1;
}

Categories