Im trying to make a popup box that causes the surrounding area to get greyed out. My issue is that the opacity of the shadow div seems to overide that of the popup. I tried changing one from absolute to fixed position and increasing the z index of the popup but neither worked.
Here is a screensot of the problem.
And below is the relevent code (ask if you need to see more)
.textPopup
{
width: 1400px;
height: 600px;
background-color: White;
position: fixed;
margin-left: auto;
margin-right: auto;
z-index: 15;
left: 0;
right: 0;
top: 50px;
bottom: 0;
opacity: 0.2;
}
#innerPopup
{
background-color: White;
width: 1350px;
height: 550px;
position: absolute;
margin-left: auto;
margin-right: auto;
z-index: 15;
left: 0;
right: 0;
top: 50px;
bottom: 0;
opacity: 1;
}
... snip
<div id="popupShadow">
</div>
<div class="textPopup">
<div id="innerPopup">
</div>
</div>
</body>
</html>
The issue you have is that #innerPopup is inside #textPopup. The opacity is then inherited by the child and cannot be overridden with it's own property.
If it is not possible to separate them, then consider using an rgba value for the background as opposed to the opacity property:
#textPopup {
background-color: rgba(255,255,255,0.2);
}
You can see it working on jsfiddle.
You'll be able to make it work as expected by making the following changes in your CSS:
#innerPopup
{
position: relative; /* change this to relative - will allow you to override the parent specified opacity */
opacity: 1;
/* other properties */
}
Related
I have an HTML/CSS pure layout and I'm using flexbox. I am developing a simple hamburger overlay menu sort of thing, but the overlay isn't fully covering the entire site -- there is no higher z-index present.
If I change the opacity to 0, the entire page goes white.
Desired Output:
Div that covers the entire page
Current Output (See Below):
HTML
<body data-theme="light" class="overlay">
...
</body>
CSS
.overlay {
opacity: 1;
background: #000;
width: 100%;
height: 100%;
z-index: 10;
top: 0;
left: 0;
position: fixed;
}
Output
You can't make the HTML body an overlay because it is the main container for the whole page, so it contains the elements you are trying to overlay.
Instead you can create a separate div for the overlay. This shouldn't have any content (unless you want content in your overlay of course). Then you can add your existing overlay class to it:
.overlay {
opacity: 0.5;
background: #000;
width: 100%;
height: 100%;
z-index: 10;
top: 0;
left: 0;
position: fixed;
}
h1, p { color: red;}
<body data-theme="light">
<div class="overlay"></div>
<h1>Hello</h1>
</body>
First you may add
.FlexContainer{position: relative;}
Next a few changes for the Overlay:
.FlexContainer .Overlay {
position: absolute;
top: 0;
left: 0;
margin: 0;
border: none;
width: 100%;
height: 100%;
background-color: rgba(013, 130, 230, 0.5);
cursor: not-allowed;
}
I have an element that requires the background to be scaled, without scaling the elements within the parent. I have achieved this by using a pseudo element to define the background, and then on hover I simply scale the pseudo element. So far, so good...
The problem is, I need some of the elements to stay inline with the scaled background, despite not scaling themselves. My original plan was to simply translate them, but I quickly realised that is not possible due to scale being based on multiples, and translate being based on percentage/pixels etc...
The obvious solution is to scrap scale and instead use margin to shrink the absolutely positioned pseudo element. However, my reservation with this is that it is bad practice to transition the margin value.
Can anybody think of a way in which I can use scale, and also maintain the alignment?
Update
I want to avoid inverse/reverse scaling at all costs as it renders badly in the browser in most cases. With that in mind, I don't think this is actually possible but will leave the question open in case anyone is aware of some CSS magic.
See the following snippet as an example:
.tile {
position: relative;
width: 500px;
height: 100px;
padding: 40px;
}
.tile:hover:before {
transform: scale(.9);
}
.tile:before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: #000;
z-index: -1;
transition: transform .3s ease-out;
}
h1 {
text-align: center;
color: white;
}
.tile > .button {
position: absolute;
right: 0;
top: 0;
display: inline-block;
background: red;
padding: 10px 15px;
color: white;
}
<div class="tile">
<h1>Hello World</h1>
<div class="button">Align Me</div>
</div>
Try scaling .tile itself and reverse-scaling its children:
.tile {
position: relative;
width: 500px;
padding: 40px;
background: #000;
transition: transform .3s ease-out;
}
h1 {
text-align: center;
}
.tile>* {
color: white;
transition: transform .3s ease-out;
}
.tile>.button {
position: absolute;
right: 0;
top: 0;
background: red;
padding: 10px 15px;
color: white;
transform-origin: 100% 0;
}
.tile:hover {
transform: scale(.9);
}
.tile:hover>* {
transform: scale(1.1);
}
<div class="tile">
<section>
<h1>Hello World</h1>
<p>I have an element that requires the background to be scaled, without scaling the elements within the parent. I have achieved this by using a pseudo element to define the background, and then on hover I simply scale the pseudo element. So far, so good...
The problem is, I need some of the elements to stay inline with the scaled background, despite not scaling themselves. My original plan was to simply translate them, but I quickly realised that is not possible due to scale being based on multiples,
and translate being based on percentage/pixels etc... The obvious solution is to scrap scale and instead use margin to shrink the absolutely positioned pseudo element. However, my reservation with this is that it is bad practice to transition the
margin value. Can anybody think of a way in which I can use scale, and also maintain the alignment?</p>
</section>
<div class="button">Align Me</div>
</div>
Another idea is animating top and right of .button:
html,
body {
width: 75%;
margin: 0;
padding: 0
}
* {
box-sizing: border-box
}
.tile {
position: relative;
width: 100%;
padding: 40px;
color: white;
}
.tile:hover:before {
transform: scale(.9);
}
.tile:before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: #000;
z-index: -1;
transition: transform .3s ease-out;
}
h1 {
text-align: center;
}
.tile>.button {
position: absolute;
right: 0;
top: 0;
background: red;
padding: 10px 15px;
color: white;
transition: .3s ease-out;
}
.tile:hover>.button {
top: 5%;
right: 5%
}
<div class="tile">
<h1>Hello World</h1>
<p>I have an element that requires the background to be scaled, without scaling the elements within the parent. I have achieved this by using a pseudo element to define the background, and then on hover I simply scale the pseudo element. So far, so good...
The problem is, I need some of the elements to stay inline with the scaled background, despite not scaling themselves. My original plan was to simply translate them, but I quickly realised that is not possible due to scale being based on multiples,
and translate being based on percentage/pixels etc... The obvious solution is to scrap scale and instead use margin to shrink the absolutely positioned pseudo element. However, my reservation with this is that it is bad practice to transition the
margin value. Can anybody think of a way in which I can use scale, and also maintain the alignment?</p>
<div class="button">Align Me</div>
</div>
The next idea is using a bit more complex code, but doing animation of transform property only:
html,
body {
width: 75%;
}
* {
box-sizing: border-box
}
.tile {
position: relative;
width: 100%;
padding: 40px;
color: white;
}
.tile:hover:before {
transform: scale(.9);
}
.tile:before,
.tile>.button {
content: '';
position: absolute;
top: 0;
left: 0;
z-index: -1;
width:100%; height:100%;
background: #000;
transition: transform .3s ease-out;
}
h1 {
text-align: center;
}
.tile>.button {
z-index: 1;
display: flex;
align-items: flex-start;
margin: 0 -100% -100% 0;
background: transparent;
transition: .3s ease-out;
pointer-events: none;
}
.tile>.button div {
padding: 10px 15px;
background: red;
cursor: pointer;
pointer-events: all;
}
.tile>.button:before {
content: '';
flex: 1 0;
}
.tile:hover>.button {
transform: translate3d(-5%, 5%, 0);
}
<div class="tile">
<h1>Hello World</h1>
<p>I have an element that requires the background to be scaled, without scaling the elements within the parent. I have achieved this by using a pseudo element to define the background, and then on hover I simply scale the pseudo element. So far, so good...
The problem is, I need some of the elements to stay inline with the scaled background, despite not scaling themselves. My original plan was to simply translate them, but I quickly realised that is not possible due to scale being based on multiples,
and translate being based on percentage/pixels etc... The obvious solution is to scrap scale and instead use margin to shrink the absolutely positioned pseudo element. However, my reservation with this is that it is bad practice to transition the
margin value. Can anybody think of a way in which I can use scale, and also maintain the alignment?</p>
<div class="button">
<div>Align Me</div>
</div>
</div>
If you are scaling by p then you are reducing the size and the new width will become width*(1 - p). Same logic for the height. You can consider the use of calc() and easily define the translate using this formula.
We divide by 2 because we reduce from both side and we will translate from 1 side
.tile {
position: relative;
width: 540px;
height: 200px;
display:flex;
align-items:center;
justify-content:center;
}
.tile:hover:before {
transform: scale(0.9);
}
.tile:hover .button{
transform: translate(calc(-540px*0.1/2),calc(200px*0.1/2));
}
.tile:before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: #000;
z-index: -1;
transition: transform .3s;
}
h1 {
text-align: center;
color: white;
margin:0;
}
.tile > .button {
position: absolute;
right: 0;
top: 0;
display: inline-block;
background: red;
padding: 10px 15px;
color: white;
transition: transform .3s ;
}
<div class="tile">
<h1>Hello World</h1>
<div class="button">Align Me</div>
</div>
You can consider CSS variables to easily change the scale value:
.tile {
position: relative;
width: 540px;
height: 200px;
display:flex;
align-items:center;
justify-content:center;
--s:0.9;
}
.tile:hover:before {
transform: scale(var(--s));
}
.tile:hover .button{
transform: translate(calc(-540px*(1 - var(--s))/2),calc(200px*(1 - var(--s))/2));
}
.tile:before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: #000;
z-index: -1;
transition: transform .3s;
}
h1 {
text-align: center;
color: white;
margin:0;
}
.tile > .button {
position: absolute;
right: 0;
top: 0;
display: inline-block;
background: red;
padding: 10px 15px;
color: white;
transition: transform .3s ;
}
<div class="tile">
<h1>Hello World</h1>
<div class="button">Align Me</div>
</div>
<div class="tile" style="--s:0.5">
<h1>Hello World</h1>
<div class="button">Align Me</div>
</div>
I'm trying to move a div with a dynamically changing height out of it's parent div and back in.
The problem is the dynamically height, otherwise I could easily set the negative height as the bottom value.
For now I just set a large negative number of pixels as the bottom value, but it isn't very nice and does not solve the problem properly. (logically this happens for small numbers: fiddle)
Hopefully the example below clarifies what I try to do.
I was thinking about using transforms instead, but i did not find a solution as well.
Of course I could do this with JavaScript, but as everyone I prefer a pure CSS solution :)
#outer {
position: relative;
width: 400px;
height: 400px;
background: black;
overflow: hidden;
}
#inner {
position: absolute;
bottom: -500px;
/*
It's working but ugly and not perfect.
The value I need would be the height of the inner div, but it is dynamic
*/
width: 100%;
background: red;
transition: 0.4s;
}
#outer:hover #inner {
transition: 0.4s;
bottom: 0;
}
<div id="outer">
<div id="inner">
Some expanding text here
</div>
</div>
You could use CSS transform:translateY(100%) property, so the height is calculated based on the element itself. Then reset the value to 0 on hover.
Inspect the element, you'll be able to see exact the height and position of it.
Also take a look of support tables for transform, and prefix it if necessary.
Updated JsFiddle
.outer {
position: relative;
display: inline-block;
width: 100px;
height: 100px;
background: grey;
overflow: hidden;
}
.inner {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
background: aqua;
transition: 0.4s;
transform: translateY(100%);
}
.outer:hover .inner {
bottom: 0;
transform: translateY(0);
}
<div class="outer">
<div class="inner">Some expanding text here..</div>
</div>
If I understand your issue, you can set a max-height for its normal and :hover state and transition it. However, you must set it to a max-height that you know will always be tall enough (which may lead to random speeds depending on how much content there is).
So something like: JS Fiddle
.outer {
position: relative;
display: inline-block;
width: 400px;
height: 400px;
background: black;
overflow: hidden;
}
.inner {
position: absolute;
bottom: 0px;
width: 100%;
background: red;
transition: 0.4s;
max-height: 0;
overflow: hidden;
}
.outer:hover .inner {
transition: 0.4s;
bottom: 0;
max-height: 40px;
}
Otherwise, I would recommend a JS solution.
Hey guys I am relatively very new to HTML and CSS and have the following difficulty I made a small input box and I am trying to add a few CSS transforms and create a small animation on the input box. Code below:
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
margin: 0;
padding: 0;
}
.input {
position: relative;
display: inline-block;
max-width: 350px;
width: 100%;
}
.akira-input {
position: absolute;
top: 0;
left: 0;
display: block;
height: 100%;
width: 100%;
background: transparent;
z-index: 10;
}
.akira-label {
display: block;
height: 100%;
padding: 0;
width: 100%;
background: #696a6e;
color: #cc6055;
cursor: text;
}
.akira-label:before {
content: '';
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
background: red;
-webkit-transform: scale3d(0.97, 0.50, 1);
transform: scale3d(0.97, 0.50, 1);
-webkit-transition: .3s;
-o-transition: .3s;
transition: .3s;
}
.label-content {
color: #000;
font-size: 1.3em;
text-transform: uppercase;
position: relative;
display: block;
text-align: center;
padding: 1.6em 0;
width: 100%;
-webkit-transition: .3s;
-o-transition: .3s;
transition: .3s;
}
<span class="input">
<input type="text" id="akira" class="akira-input">
<label for="akira" class="akira-label">
<span class="label-content">Akira</span>
</label>
</span>
My difficulty is, if I apply position:relative to <span class="label-content">Akira</span>, it shows, if I remove position:relative , that element disappears from view.
My question is why is position:relative functioning like z-index?
Can somebody elaborate ??
EDIT :: refering to Justinas answer , i have the folloing question ,
Does applying position:relative places an element
higher in the stack , even without applying z-index ??
z-index is only working for non-static elements, so when you remove position: relative than element becomes statically positioned and moves below higher index elements (disappears from view). When you add position: relative to element, than z-index will take effect and so element appears in your view.
Also position and z-index is two different properties
position - how element is positioned according to other elements on page. Default to static
z-index - how high element is in z-axis (z-index: 2 - is behind element with z-index: 10). Default to 5
.wrapper {
position: relative;
}
#static {
position: static;
z-index: 999;
width: 400px;
height: 150px;
background-color: #ddd;
padding: 3px;
}
#top-1 {
position: absolute;
z-index: 10;
left: 8px;
top: 45px;
width: 330px;
height: 80px;
background-color: #888;
padding: 3px;
}
#relative {
position: relative;
z-index: 11;
background-color: #88a;
width: 330px;
height: 80px;
padding: 3px;
top: 30px;
left: 8px;
}
#top-2 {
position: absolute;
z-index: 10;
left: 0;
top: 0;
width: 400px;
height: 150px;
background-color: #dda;
padding: 3px;
}
<div class='wrapper'>
<div id="static">
I'm static, so behind #top-1, but have z-index higher than #top-1... Means z-index has no effect.
<br/>Text that is not visible, because behind #top-1 element
</div>
<div id='top-1'>
I'm above #static, because i have non-static position, so my z-index has effect.
</div>
</div>
<hr/>
<div class='wrapper'>
<div id="relative">
I'm relative and above #top-2, because my z-index higher than #top-2... Means z-index has taken effect.
</div>
<div id='top-2'>
I'm below #relative, because i have lover z-index.
<br/>Text that is not visible, because behind #top-1 element
</div>
</div>
z-index only works on positioned elements so position:absolute, position:relative or position:fixed
It does not behave like a z-index, because z-index specifies an ordering rule, but not the way how the element is displayed.
position: relative; says to go to the relative mode where it can compete the absolutely positioned elements.
Your problem here is that :before pseudo-element is a hierarchical sibling of span, and it takes the whole available parent width. So it fully covers a static span element.
When you make it relative, it becomes shown because when z-index is not specified for both non-static elements they are shown in the same order like they are placed in HTML (so element which is defined in HTML later is always on top).
Your structure is:
label
:before
span
so the span becomes visible.
This question already has answers here:
Why does z-index not work?
(10 answers)
Closed 7 years ago.
A CSS animation is continuously playing behind an image. When the image is not loaded it will display, but when loaded the image will overlap the animation. I'm using z-index to achieve this, but it's not working.
The image should hide loading animation with the z-index property.
Note: I can't use any javascript solution to hide the loading animation and show it after image load.
CSS / HTML / Demo
.leftprev {
overflow:auto;
position:absolute;
height:99%;
width:85%;
}
.loadingslide {
z-index: 50; /* Loading div's z-index */
}
.spinner.big {
display: block;
height: 40px;
}
.spinner {
bottom: 0;
display: none;
font-size: 10px;
height: 30px;
left: 0;
margin: auto;
position: absolute;
right: 0;
text-align: center;
top: 0;
width: 60px;
}
.spinner.big > div {
width: 6px;
}
.spinner > div {
animation: 1.2s ease-in-out 0s normal none infinite stretchdelay;
background-color: #333;
display: inline-block;
height: 100%;
width: 6px;
}
a {
color: #470a09;
text-decoration: none;
}
.slideshow .slidebro .leftprev #slideshowpic {
display: block;
margin: 0 auto;
width: auto;
z-index: 100; /* image's z-index */
}
<div class="leftprev">
<div class="loadingslide"> <!-- Loading Animation div (should be running in background of the image) -->
<div id="tracking" class="spinner big">
<div class="rect1"></div>
<div class="rect2"></div>
<div class="rect3"></div>
<div class="rect4"></div>
<div class="rect5"></div>
</div>
</div>
<a id="targetslide" target="_blank" title="Click to view fit to screen" href="">
<img src="http://www.placehold.it/500" alt="" id="slideshowpic" /> <!-- The image (should mask the loading animation div) -->
</a>
</div>
You have to add position to the element that you want to apply z-index.
From CSS-tricks:
The z-index property in CSS controls the vertical stacking order of
elements that overlap. As in, which one appears as if it is physically
closer to you. z-index only effects elements that have a position
value other than static (the default).
http://css-tricks.com/almanac/properties/z/z-index/
To position the loading animation correctly:
Place the loading div inside the container
Set the container as position: relative so that the loading div is positioned in relation to it
To hide the loading animation when the image is loaded:
The loading div is given z-index: 1
The image is given position: relative so that it can have a z-index property
The image is given z-index: 2 and will overlap
In this example the image is half the width of the container and you can see how it overlaps the loading div.
CSS / HTML / Demo
html, body {
height: 100%;
margin: 0;
}
.content {
height: 500px;
width: 500px;
background: #e91e63;
margin: 0 auto;
position: relative;
}
.content img {
z-index: 2;
position: relative;
width: 250px;
height: 500px;
}
.loading {
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100px;
height: 1em;
padding: 20px;
background: #FF0;
text-align: center;
font-weight: bold;
z-index: 1;
}
<div class="content">
<div class="loading">I am loading</div>
<img src="http://www.placehold.it/250X500" />
</div>