I have an HTML page where I need to make a deeply nested element appear above a neighboring ancestor.
Here is an example JSFiddle: https://jsfiddle.net/nLa607g5/1/
This HTML structure can’t be changed. Using CSS (preferably) or JavaScript, is there any way I can make the red button appear on top of the overlay, but the blue portion appear behind the overlay?
The following are the two main classes that deal with the overlay and button:
.overlay {
background-color: rgba(0, 0, 0, 0.3);
backdrop-filter: blur(2px);
border-radius: 5px;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
#cntrl {
float: left;
}
.modal {
overflow: auto;
display: block;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1050;
}
.dialog {
background: blue;
width: 100px;
height: 100px;
display: block;
}
.btn {
margin-top: 20px;
position: relative;
background: red;
}
<div class="overlay"></div>
<div id="app">
<div id="cntrl">
<div>
<div>
<div class="modal">
<div class="dialog">
<span>should appear behind overlay</span>
<div class="content">
<div class="footer">
<button class="btn">
Should appear on top of overlay
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Impossible with CSS and no HTML. JavaScript is the only option. Basically, you append the overlay to the footer and the button to the overlay -- exactly what you'd do with HTML.
const overlay = document.querySelector('.overlay');
const footer = document.querySelector('.footer');
const button = document.querySelector('.btn');
footer.append(overlay);
overlay.append(button);
.overlay {
background-color: rgba(0, 0, 0, 0.3);
backdrop-filter: blur(2px);
border-radius: 5px;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
#cntrl {
float: left;
}
.modal {
overflow: auto;
display: block;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1050;
}
.dialog {
background: blue;
width: 100px;
height: 100px;
display: block;
}
.btn {
margin-top: 20px;
position: relative;
background: red;
}
<div class="overlay"></div>
<div id="app">
<div id="cntrl">
<div>
<div>
<div class="modal">
<div class="dialog">
<span>should appear behind overlay</span>
<div class="content">
<div class="footer">
<button class="btn">
Should appear on top of overlay
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Related
Im not really sure why the span tag is not closing
Does it have to do with my selection being a div in js?
Please let me know what I can change in order to make this work.
Ive tried to switch out the labels of the classes and tested selectors as well
Here is my code.
document.querySelectorAll('.imageContainer div').forEach(image => {
image.onclick = () => {
document.querySelector('.popup-image').style.display = 'block';
document.querySelector('.popup-image img').div = image.getAttribute('data-img');
}
});
document.querySelector('.popup-image span').onclick = () => {
document.querySelector('.popup-image').style.display = 'none';
};
/* modal */
.container .popup-image {
position: fixed;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.641);
height: 100%;
width: 100%;
z-index: 100;
display: none;
}
.container .popup-image span {
position: absolute;
top: 0;
right: 10px;
font-size: bolder;
color: #fff;
cursor: pointer;
z-index: 100;
}
.container .popup-image img {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border: 5px solid #fff;
width: 750px;
object-fit: cover;
}
#media only screen and (max-width: 600px) {
.container .popup-image img {
width: 99%;
}
}
<div class="imageContainer">
<div class="entry work-entry branding">
<div class="entry-image image imageBG" data-img="./src/assets/img/feature1.jpeg">
</div>
<div class="work-entry-hover">
<div class="work-entry-content">
<div class="work-entry-title">Brand</div>
<div class="work-entry-cat">Los Angeles, CA</div>
</div>
</div>
</div>
<!-- modal -->
<div class="popup-image">
<img src="./src/assets/img/feature1.jpeg" alt="">
<span>×</span>
</div>
</div>
Since the 'x' button is inside the other element, the function to set display: block is being called when you click on the span, which is overriding the display: none; that you're setting. You can stop this by running e.stopPropagation(); in the event handler, which will prevent the click event from triggering on any parent elements.
document.querySelectorAll('.imageContainer div').forEach(image => {
image.onclick = () => {
document.querySelector('.popup-image').style.display = 'block';
document.querySelector('.popup-image img').div = image.getAttribute('data-img');
}
});
document.querySelector('.popup-image span').onclick = (e) => {
e.stopPropagation();
document.querySelector('.popup-image').style.display = 'none';
};
/* modal */
.container .popup-image {
position: fixed;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.641);
height: 100%;
width: 100%;
z-index: 100;
display: none;
}
.container .popup-image span {
position: absolute;
top: 0;
right: 10px;
font-size: bolder;
color: #fff;
cursor: pointer;
z-index: 100;
}
.container .popup-image img {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border: 5px solid #fff;
width: 750px;
object-fit: cover;
}
#media only screen and (max-width: 600px) {
.container .popup-image img {
width: 99%;
}
}
<div class="imageContainer">
<div class="entry work-entry branding">
<div class="entry-image image imageBG" data-img="./src/assets/img/feature1.jpeg">
</div>
<div class="work-entry-hover">
<div class="work-entry-content">
<div class="work-entry-title">Brand</div>
<div class="work-entry-cat">Los Angeles, CA</div>
</div>
</div>
</div>
<!-- modal -->
<div class="popup-image">
<img src="./src/assets/img/feature1.jpeg" alt="">
<span>×</span>
</div>
</div>
I have a simple HTML and CSS overlay that triggers at certain actions. I would like to display the overlay on certain part of the page.
I have side-bar menu on the left attached to it the main body. using position: fixed; is good to create an overlay that covers all the page but I want overlay to cover only the page in where its displayed beside that it has to set on top of the current content as if I am using position: fixed; How can I do this.
HTML Code that is placed in the body content of the page:
.backdrop {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: black;
opacity: 0.3;
background-size: 100% 100%;
}
.loadingSpan {
display: inline-block;
align-items: center;
display: flex;
justify-content: center;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
color: red;
}
<div class="backdrop" id="LoadingContainer">
<div class="loadingSpan">
<h1 id="LoadingText">Loading</h1>
<div class="spinner-grow" role="status">
<span class="sr-only">Loading</span>
<span class="sr-only"></span>
</div>
<div class="spinner-grow" role="status">
<span class="sr-only">Loading</span>
</div>
<div class="spinner-grow" role="status">
<span class="sr-only">Loading</span>
</div>
</div>
</div>
The overly works fine but it covers the whole page alongside with the side menu so I want to fix this just to cover the page that its current its code placed at.
Side Menu:
<section class="sidebar">
<ol class="quickinfo">
<li class="quickinfo_item">
<span class="quickinfo_text">Menu1</span>
<span class="quickinfo_text">Menu2</span>
</li>
</ol>
</section>
CSS:
.sidebar {
background: #222d32;
flex: 1;
max-width: 15%;
height: 100%;
color: white; }
.sidebar_item {
display: flex; }
Layout:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<section class="container_body container-fluid">
#{ Html.RenderAction("Sidebar", "Ui"); }
<section class="content container-fluid">
#RenderBody()
</section>
</section>
</body>
</html>
Use position: relative for the container and position: absolute for the overlay. Then put the overlay inside the container. Example:
body {
font-family: sans-serif;
margin: 0;
}
.container {
width: 300px;
height: 200px;
border: 1px solid black;
position: relative;
}
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
text-align: center;
background-color: rgba(0,0,0,0.5);
color: white;
}
<h1>Outside the Container</h1>
<div class="container">
Container Content
<div class="overlay">
Overlay Content
</div>
</div>
Change .backdrop position: absolute; and set its container to position: relative;
fixed means that it's position is relative to the view port (usually). absolute means relative to the containing block
I have a hamburger side menu and header element and when I click that hamburger menu I want the header to be displayed initial and the header's width grows slowly to left how do I do that.
header {
width: 0px;
background-color: black;
padding-bottom: 10px;
display: none;
position: absolute;
}
.hamburger {
width: 20px;
background-color: black;
margin: 3px;
height: 3px;
top: 22px;
left: 100px;
}
<header>.</header>
<div id="main">
<div class="hamburger"></div>
<div class="hamburger"></div>
<div class="hamburger"></div>
</div>
You can use css transition to animate when header width goes from 0 to 100%
document.getElementById('main').onclick = function() {
document.getElementById('header').classList.add('show');
}
html,
body {
padding: 0;
margin: 0;
}
header {
width: 0px;
background-color: black;
position: absolute;
transition: all 0.5s;
overflow: hidden;
}
header.show {
width: 100%;
}
.hamburger {
width: 20px;
background-color: black;
margin: 3px;
height: 3px;
top: 22px;
left: 100px;
}
<header id="header">
<div style="padding: 1em;">
header
</div>
</header>
<div id="main">
<div class="hamburger"></div>
<div class="hamburger"></div>
<div class="hamburger"></div>
</div>
I have several divs with absolute position on top of primary div which has relative position (duh). I am trying to make one div change its background-color etc when hovering another div within same parent div.
Now, I'm aware of adjacent-div classes but they don't seem to work (maybe because of absolute positioning).
Below is an example of my code (actual is a lot bigger). What would be best way to change for e.g. m2wrap-back width & color when hovering on m2wrap-hover (which overlays 100% on other divs)?
P.S. If CSS alone ain't an option, a jQuery solution can also work.
<div class="m2wrap">
<div class="m2wrap-back">
<h3 class="m2wrap-back-title">Title</h3>
</div>
<h3 class="xhfb-text"> Some text here.. </h3>
<div class="m2wrap-bz1"></div>
<div class="m2wrap-bz2"></div>
<div class="m2wrap-hover"></div>
</div>
<style>
.m2wrap {
position: relative
}
.m2wrap-back {
position: absolute;
top: 15px;
left: 0;
width: 110px;
height: 0;
text-align: center;
vertical-align: middle;
}
.m2wrap-hover {
position: absolute;
width: 100%;
height: 100%;
z-index: 2;
border-radius: 4px;
opacity: 0.6;
cursor: pointer;
}
div.m2wrap-hover:hover {
background-color: #bf0000;
}
</style>
You can not do it with pure css and your current html structure, need javascipt or jquery to do this.
Example:
$('.m2wrap-hover').hover(function() {
$(this).closest('.m2wrap').find('.m2wrap-back').addClass('hover');
}, function() {
$(this).closest('.m2wrap').find('.m2wrap-back').removeClass('hover');
})
.m2wrap {
position: relative
}
.m2wrap-back {
position: absolute;
top: 15px;
left: 0;
width: 110px;
height: 0;
text-align: center;
vertical-align: middle;
}
.m2wrap-hover {
position: absolute;
width: 100%;
height: 100%;
z-index: 2;
border-radius: 4px;
opacity: 0.6;
cursor: pointer;
}
div.m2wrap-hover:hover {
background-color: #bf0000;
}
.m2wrap-back.hover {
width: 120px;
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="m2wrap">
<div class="m2wrap-back">
<h3 class="m2wrap-back-title">Title</h3>
</div>
<h3 class="xhfb-text"> Some text here.. </h3>
<div class="m2wrap-bz1"></div>
<div class="m2wrap-bz2"></div>
<div class="m2wrap-hover">hover here</div>
</div>
Or if you want to use just css, you need to change the order of your elements (because it has position: absolute so the order doesn't matter):
.m2wrap {
position: relative
}
.m2wrap-back {
position: absolute;
top: 15px;
left: 0;
width: 110px;
height: 0;
text-align: center;
vertical-align: middle;
}
.m2wrap-hover {
position: absolute;
width: 100%;
height: 100%;
z-index: 2;
border-radius: 4px;
opacity: 0.6;
cursor: pointer;
}
div.m2wrap-hover:hover {
background-color: #bf0000;
}
.m2wrap-hover:hover + .m2wrap-back {
width: 120px;
color: red;
}
<div class="m2wrap">
<h3 class="xhfb-text"> Some text here.. </h3>
<div class="m2wrap-bz1"></div>
<div class="m2wrap-bz2"></div>
<div class="m2wrap-hover">hover here</div>
<div class="m2wrap-back">
<h3 class="m2wrap-back-title">Title</h3>
</div>
</div>
code jsFiddle
I applied jquery's click function to 'li#info' element. But when I click, it perform jquery to element of different parent also ('#theme div#info-overlay').
I want, whenever 'li#info' is clicked on the parent element('#theme') then it perform function to its child element only(div#info-overlay).
Like in the code, by clicking on 'Fe' it open overlay on both the block. But i want it to show overlay only to the block for which 'Fe'is clicked.
sorry, I am new in jquery.
I got your point. you just need to change one line of code
because both divs have same ids thats why both are appearing on click
and it's not a good practice to use same id multiple time on a single file.
it will make issue somewhere sometime.
i have change this line
$("div#info-overlay").toggle('100');
into this
$(this).parents('#theme').find("#info-overlay").toggle('100');
check this
JS Fiddle
use this to find div $(this).parents('#theme').find("#info overlay").toggle('100');
$(document).ready(function(){
$("div#theme").hover(function(){
$(".theme .header *").show();
$(".theme .header .overlay").hide();
},function(){
$(".theme .header *").hide();
});
$("li#info").click(function(){
$(".theme .header .overlay").hide();
$(this).parents('#theme').find("#info-overlay").toggle('100');
// $("div#info-overlay").toggle('100');
});
});
/*
theme block
*/
.theme{
width: 100%;
height: 250px;
background-color: #fff;
margin: 20px auto;
}
.theme .header{
width: 100%;
height: 200px;
position: relative;
background-color: #eee;
}
.theme .header *{
display: none;
}
.theme .header .overlay{
position: absolute;
background-color: #fff;
left: 60px;
top: 10px;
width: 83%;
height: 180px;
z-index: 80;
}
.theme .header .about{
position: absolute;
left: 10px;
top: 10px;
}
.theme .header .about li{
display: block;
height: 40px;
width: 40px;
border-radius: 50%;
background-color: #FED200;
opacity: .5;
color: #fff;
padding: 5px 10px;
margin: 5px 0;
}
.theme .footer{
width: 100%;
height: 50px;
padding: 0 20px;
}
.theme .footer .left{
width: 85%;
display: inline-block;
overflow-y:hidden;
height: 50px;
float: left;
padding: 10px 0;
}
#media screen and (min-width:620px) {
.theme{
width: 70%;
}
}
#media screen and (min-width:720px) {
.theme{
width: 49%;
display: inline-block;
}
}
#media screen and (min-width:920px) {
body .container.theme-holder {
width: 70%;
}
}
#media screen and (min-width:1024px) {
body .container.theme-holder {
width: 95%;
}
.theme{
width: 32%;
}
}
#media screen and (min-width:1200px) {
body .container.theme-holder {
width: 85%;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="theme" class="theme">
<div class="header">
<div class="about">
<li id="info">Fe</li>
</div>
<div id="info-overlay" class="overlay">
info
</div>
</div>
<div class="footer">
<div class="left">
<div class="name">
<p>Corporate sdfsfdsfdsfsd</p>
</div>
</div>
</div>
</div>
<div id="theme" class="theme">
<div class="header">
<div class="about">
<li id="info">Fe</li>
</div>
<div id="info-overlay" class="overlay">
info
</div>
</div>
<div class="footer">
<div class="left">
<div class="name">
<p>Corporate dfsasdfdsafs</p>
</div>
</div>
</div>
</div>