How to overlay "transformed" element? - javascript

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;
}

Related

How to stack elements without using z-index

I have this code:
<nav>
<div class="slider" id="slider"></div>
<div class="titleGroup">
<h2 onclick="selectArticles()" id="articlesButton" class="active">Articles</h2>
<h2 onclick="selectSocial()" id="socialButton">Social</h2>
</div>
</nav>
I need to make the slider appear on top of titleGroup but under its h2 childs, is there a way to do it using javascript? Making the h2s appear on top of everything would work too.
I tried doing it with z-index but obviously it doesn't work because z-index is relative to the parent.
Since you asked for JavaScript solution... you can prepend it to be the first child of the .titleGroup. But of course a better approach would have been to fix the HTML or try with z-index.
titleGroup.prepend(slider)
.titleGroup {
background: red;
height: 150px;
}
h2 {
position:relative;
background: black;
}
.slider {
opacity: 0.5;
background: yellow;
height: 100px;
width: 100%;
position: absolute;
}
<nav>
<div class="slider" id="slider">I am slider</div>
<div class="titleGroup" id="titleGroup">
<h2 onclick="selectArticles()" id="articlesButton" class="active">Articles</h2>
<h2 onclick="selectSocial()" id="socialButton">Social</h2>
</div>
</nav>
It's actually possible to solve your current problem using z-index and no JavaScript
(assuming you're not doing something funny with your titleGroup).
nav{
position:relative;
}
.titleGroup {
background: red;
height: 150px;
border: 1px solid yellow;
}
#slider{
z-index:1;
position: absolute;
top: 5px;
background: green;
color: white;
height: 80px;
left: 5px;
width: calc(100% - 10px);
padding: 5px;
box-sizing: border-box;
}
#slider::before{
content: "Slider in front of titleGroup background, but behind h2"
}
h2 {
position: relative;
background: cyan;
z-index: 2;
}
<nav>
<div class="slider" id="slider"></div>
<div class="titleGroup" id="titleGroup">
<h2 onclick="selectArticles()" id="articlesButton" class="active">Articles</h2>
<h2 onclick="selectSocial()" id="socialButton">Social</h2>
</div>
</nav>
Note that .titleGroup has no special value for position (or z-index for that matter), so no new stacking context is created.
(And if a css statement somehow affects your titleGroup element’s position property, you can use position:unset or position:static)
More about stacking context: Link1 (The stacking context
)
The following has an example where elements that are not siblings can be controlled just using z-index: Link2 (Stacking context example 1
)
In my example, h2 and #slider are not siblings, but since .titleGroup has no stacking context, in effect the behavior of z-indexes is comparable that of siblings.
Also note that this fails if your .titleGroup has opacity value less than 1, as it creates a new stacking context, and similarly if you have a special filter, etc. (described in the first link).

How to make a div element expand upwards using css and JS

I have found a lot of answers on this, but most of the answers include jquery and dont fully answer my question. I have a DIV with several elements nested within it, and those nested element expand upwards, but the DIV does not. This is what i have:
HTML:
<style>
.botnav {
display:flex;
align-items:flex-end;
height: 0;
width: 100%;
position: fixed;
z-index: 2;
top: 50%;
left: 0;
overflow-y:hidden;
background-color: #111;
transition: height 0.5s;
}
.botnav .closebtn{
position: absolute;
top: 0;
right: 25px;
font-size: 36px;
margin-left: 50px;
color: whitesmoke;
}
</style>
<div id='botNav' class='botnav'>
<a href='javascript:void(0)' class='closebtN' onclick='closeBotNav()'>×</a>
</div>
<h1 style='position:fixed;cursor:pointer;font-size:25px;color:ghostwhite;background-color:#111;width:25px;height:25px;top:95%;left:95%;' id='s2' onclick="openBotNav()">^</h1>
Javascript:
function openBotNav() {
document.getElementById('botNav').style.height = '300px';
}
function closeBotNav() {
document.getElementById("botNav").style.height = "0";
}
and as you can see the div will expand down, not up. this is my issue.
Remove top:50% and replace it to bottom:0% on "botnav" class. This will do the trick
Instead of changing styles with js, you could toggle a class that change the styles.
document.querySelector(".btn").addEventListener("click", () => {
document.querySelector(".botnav").classList.toggle("open")
})
.botnav{
background-color:orange;
height:0px;
overflow-y:hidden;
transition-duration:1000ms;
}
.botnav.open{
height:100px;
}
<button class="btn">open/close</button>
<div class="botnav">
<div>A</div>
<div>B</div>
<div>C</div>
</div>
Note that if you need 2 different element to open or close your div, you can make one event to open it with .classList.add("open") and an other with .classList.remove("open")

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>

CSS Overlay not allowing DIv on top [duplicate]

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.

Can I use `overflow: scroll` on a div with variable height?

Is it possible to use overflow: scroll on a div that has height set to auto?
I have a div with an unordered list inside of it. The amount of items in the list is variable so there is no way I can use a fixed height. The div that contains the unordered list is where the scrollbars need to be, here is my code:
#page {
height: auto; /* default */
overflow-y: scroll;
overflow-x: hidden;
}
As stated, the unordered list is contained within the #page div. The height of the page is assigned by the unordered list's value. Is there a way to make overflow: scroll work on a div with variable height like this or must I use JavaScript to do this?
Thanks
One way of approaching this design...
Suppose that you have the following HTML:
<div class="main">
<div class="inner">
<ul>
<li>Some list items...</li>
...
</ul>
</div>
</div>
The .main block is fitted to the page, for example, by absolute positioning:
.main {
border: 2px dashed blue;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
The .inner block holds the navigation list that can cause scrolling:
.inner {
border: 2px dotted red;
position: absolute;
top: 10px;
bottom: 10px;
left: 10px;
right: 10px;
overflow-y: scroll;
}
In this example, I constrain the height of the .inner block to fit within .main,
and set overflow-y: scroll, which creates a scroll bar contained within the edges
of the container block.
You may have to adapt this to your mobile platform, but the concept should still apply.
Demo fiddle: http://jsfiddle.net/audetwebdesign/ac4xT/
Simply put, if it has variable height (auto), it will never have overflow in the y axis (vertically), because the div will always grow to fit its contents.
overflow: scroll will force it to present a scrollbar, but it will always be disabled, because the contents will never extend beyond the displayed pane.
If you want vertical scrolling, you have to define a height, either in px, %, or em.
If you do height: 100%, the div will fill the height of the page, and scroll content that extends beyond the window's viewport height.
If you have a header area, try something like this:
body {
margin: 0;
}
#header {
position: absolute;
width: 100%;
height: 40%;
background-color: #ccc;
}
#body {
position: absolute;
top: 40%;
width: 100%;
height: 60%;
overflow-y: auto;
background-color: #eee;
}
<body>
<div id="header">
<p>Header</p>
</div>
<div id="body">
<p>Body</p><p>Body</p><p>Body</p><p>Body</p><p>Body</p><p>Body</p><p>Body</p>
<p>Body</p><p>Body</p><p>Body</p><p>Body</p><p>Body</p><p>Body</p><p>Body</p>
</div>
</body>
For a fixed-height header (per the comments), use absolute positioning with a top and botom value to position the scrollable div below it:
body {
margin: 0;
}
#header {
position: absolute;
width: 100%;
height: 60px;
background-color: #ccc;
}
#body {
position: absolute;
top: 60px;
bottom: 0px;
width: 100%;
overflow-y: auto;
background-color: #eee;
}
<body>
<div id="header">
<p>Header</p>
</div>
<div id="body">
<p>Body</p><p>Body</p><p>Body</p><p>Body</p><p>Body</p><p>Body</p><p>Body</p>
<p>Body</p><p>Body</p><p>Body</p><p>Body</p><p>Body</p><p>Body</p><p>Body</p>
</div>
</body>
Why not use max-height on the div?
max-height sets the maximum height to which an element can expand. I suppose what you want is the div to never go out of the screen. So you can set a max-height and then overflow: auto;

Categories