I'm trying to figure out why when setting an inline background-image all other background properties are not working.
External CSS:
background: linear-gradient(rgba(0,0,0,.8), rgba(0,0,0,.8)), url("http://lorempixel.com/1400/900/");
Result:
But when an inline background-image is added the gradient property seems to be ignored.
Inline CSS
<div class="intro-img" style="background-image: url('http://lorempixel.com/1400/900/')">
Result:
you're actually overriding your background property with your
background-image: url('XXX')
You could fix it by also adding your gradient to your inline style
Another solution would be using another element / pseudo element to handle your gradient
#test, #test2 {
width: 600px;
height: 400px;
}
.is-overlayed {
position: relative
}
.is-overlayed::after {
content: '';
background: linear-gradient(rgba(0,0,0,.6), rgba(0,0,0,.6));
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.text {
color: #fff;
}
.above-overlay {
z-index: 1;
position: relative;
}
<div id="test" class='is-overlayed' style='background-image:url("http://lorempixel.com/1400/900/")'>
<p class='text above-overlay'>ABOVE OVERLAY</p>
<p class='text under-overlay'>UNDER OVERLAY</p>
</div>
Related
From my understanding, ::before should appear below the element, and ::after should appear above of the element (in terms of z-index).
In the following example I am trying to make just the background color darker (not the foreground color) when one hovers over the button. Even though I used ::before it still appears in front. Why? I know I could fix it with z-index, but according to this comment which has 6 upvotes:
I think it's better to use :before so you get the right stacking order without playing with z-index.
I should not have to, and the order should be correct?
.parent {
--my-color: red;
}
button {
color: blue;
background-color: var(--my-color);
padding: 8px 16px;
position: relative;
}
button:hover {
background-color: transparent;
}
button:hover::before {
display: block;
content: "";
position: absolute;
top: 0; left: 0; width: 50%; height: 100%; /* width is 50% for debugging (can see whats below) */
background-color: var(--my-color);
filter: brightness(80%);
}
<div class="parent">
<button type="button">CLICK ME</button>
</div>
There's no difference between ::before and ::after regarding the z-index or z-axis order. By default both will be placed in front of their parent, covering it (if their position is defined accordingly). To achieve z-axis layering beyond that, you need to actually use a z-index (besides a combination of relative and absolute position).
Addition after comment:
In the snippet below there are two variations of the situation. The only difference if that once ::after is used, once ::before, both times without a z-index, and both time with the same result, i.e. the pseudo element covering its parent:
.parent {
--my-color: red;
}
button {
color: blue;
background-color: var(--my-color);
padding: 8px 16px;
position: relative;
}
button:hover {
background-color: transparent;
}
.parent:nth-child(1) button:hover::before {
content: '';
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: var(--my-color);
filter: brightness(80%);
}
.parent:nth-child(2) button:hover::after {
content: '';
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: var(--my-color);
filter: brightness(80%);
}
<div class="parent">
<button type="button">CLICK ME</button>
</div>
<div class="parent">
<button type="button">CLICK ME</button>
</div>
So, to come back to your question in your second comment: Yes, they are wrong - you need to use a z-index to move the pseudo element behind the parent.
So your actual solution should look like this, using a negative z-index: -1; for the pseudo element (and you could as well use ::after here, it doesn't matter...).
.parent {
--my-color: red;
}
button {
color: blue;
background-color: var(--my-color);
padding: 8px 16px;
position: relative;
}
button:hover {
background-color: transparent;
}
button:hover::before {
content: '';
position: absolute;
z-index: -1;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: var(--my-color);
filter: brightness(80%);
}
<div class="parent">
<button type="button">CLICK ME</button>
</div>
I have a DIV with "width: 100%", and after some time it moves to a different width (for example "width: 50%") with a nice transition. I want that the part which is going to decrease to get a different color. How do I do it?
.container {
width: 80%;
height: 50px;
}
.bar {
background-color: red;
width: 100%;
height: 100%;
transition-duration: 1s;
}
<div class="container">
<div class="bar"></div>
</div>
You can simply put another bar exactly behind this bar. Set it's z-index to 1. And your current bar's z-index to a higher number.
The bar that is in the back, has a black color like you wanted.
Now when the red bar decrease it's width, the one in the back becomes visible.
Here you go, the most basic working example.
(Try hovering the bar and see it moving)
By simply overlaying a pseudo-element over the static .bar element, with position:absolute, it is places above the bar and has dynamic width which you should change.
.container {
width: 80%;
height: 50px;
}
/* static background bar */
.bar {
--progress: 80%; /* css variable */
position: relative;
background-color: salmon;
width: 100%;
height: 100%;
}
/* This is the part which moves: */
.bar::before{
content: '';
background-color: darkred;
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
width: var(--progress);
transition: 1s;
}
.bar:hover {
--progress: 20%;
}
<div class="container">
<div class="bar"></div>
</div>
This solution uses a linear-gradient where I animate the background-size. I placed a fully black gradient on the .container, and a red one on the .bar, where I put a transition: background-size 1s on the black .container.
By using javascript to change a CSS variable, I can get the bar to animate.
Added a range to show-case the result.
Do note that it's always better to specify what attribute to animate with transiation, because otherwise the browser loops through all animatable properies, which can create janky animations.
let rangeInput = document.querySelector('input[type="range"');
let containerDiv = document.getElementById("container");
if (rangeInput) {
rangeInput.addEventListener('change', (event) => {
let newValue = event.target.value;
containerDiv.style.setProperty('--bar-width', `${newValue}%`);
});
}
input[type="range"] {
width: 80%;
margin-top: 1rem;
}
#container {
--bar-width: 100%;
width: 80%;
height: 50px;
background: linear-gradient(black, black);
transition: background-size 1s;
}
/* added "div" to obtain a higher specificity, to override the default background properties. */
div#container,
div.bar
{
background-repeat: no-repeat;
background-size: var(--bar-width);
}
.bar {
background: linear-gradient(red, red);
width: 100%;
height: 100%;
}
<div id="container">
<div class="bar"></div>
</div>
<input type="range" value="100" />
Is it possible to have the CSS cursor property of a div propagate through a transparent div that overlays it?
Let me illustrate with a mock-up: https://jsfiddle.net/azL1ot2d/
With the following HTML code:
<div id="page">
<div id="clickable">Click me!</div>
<div id="glasspane">
<div id="other">Some glass-pane content</div>
</div>
</div>
And the following CSS code (reduced to the important parts):
#page {
position: absolute;
width: 100%;
height: 100%;
}
#clickable {
position: absolute;
top: 100px;
left: 100px;
background-color: orange;
cursor: pointer;
}
#glasspane {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
background-color: transparent;
}
#other {
...
}
Notice how I set the cursor property on the clickable div, but the div is entirely covered by the glasspane div (which I use for effects, dialogs, ...). Is it possible to have the mouse-cursor change to the link-pointer if it hovers above the clickable-div even though the div is covered? In other words: Can I make the glasspane transparent to cursor settings? (I'd prefer not to use JavaScript for this)
Yes you can but there is no IE support, there you go : JSFiddle
The trick is to use pointer-events: none; on the top layer :)
#glasspane {
pointer-events: none;
}
I have a div with a background image that should be covered with a mask effect. On that div should be some content. I'm trying to get the content to be over the mask but for some reason it isn't working.
I added a jsFiddle:
http://jsfiddle.net/FHt9d/
Here is the code:
Html:
<div id="container">
<div id="mask"></div>
<div id="content"><h1>This is a header</h1></div>
</div>
Css
#container
{
width: 100%;
height: 246px;
position: relative;
background-repeat: no-repeat;
background-size: 100%;
background-image: url('http://upload.wikimedia.org/wikipedia/commons/d/d8/Skyline_oklahoma_city.JPG')
}
#mask
{
z-index: 1;
height: 100%;
width: 100%;
background-color: rgba(75,139,228,.8);
position: absolute;
top: 0;
left: 0;
}
#content h1
{
z-index:2;
font-size: 32;
color: #fff;
}
The text should not be covered by the mask. Any help would be greatly appreciated,
Thanks!
try this (you missed a position: relative;):
#content h1 {
color: #FFFFFF;
position: relative; //missed
z-index: 2;
}
The elements that have
position: absolute
are always on top. Same thing applies to
position: fixed;
They always float above the elements in a browser.
To minimize this, you use
z-index: value;
For the elements with position value set, you can use:
z-index: 1;
and change it for the element you want to be above others
z-index: 2; /* or more than 2 */
This will do the job.
You missed a position: relative; on the #content h1. Indeed, z-index applies only on positionned elements.
I'm struggling to make this render right in my browser (Chrome). I have a wrapper holding all the elements of the HTML, and I want to have a DIV (lets call it div-1) that hold a image, and has a overlay div on top of it to the left, like I sketched in this picture...any quick solutions?
Here's a pure CSS solution, similar to DarkBee's answer, but without the need for an extra .wrapper div:
.dimmed {
position: relative;
}
.dimmed:after {
content: " ";
z-index: 10;
display: block;
position: absolute;
height: 100%;
top: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.5);
}
I'm using rgba here, but of course you can use other transparency methods if you like.
Using CSS3 you don't need to make your own image with the transparency.
Just have a div with the following
position:absolute;
left:0;
background: rgba(255,255,255,.5);
The last parameter in background (.5) is the level of transparency (a higher number is more opaque).
Example Fiddle
.foo {
position : relative;
}
.foo .wrapper {
background-image : url('semi-trans.png');
z-index : 10;
position : absolute;
top : 0;
left : 0;
}
<div class="foo">
<img src="example.png" />
<div class="wrapper"> </div>
</div>
For a div-Element you could just set the opacity via a class to enable or disable the effect.
.mute-all {
opacity: 0.4;
}
Like the answer previous, but I'd put ::before, just for stacking purposes. If you want to include text over the overlay (a common use case), using ::before will should fix that.
.dimmed {
position: relative;
}
.dimmed:before {
content: " ";
z-index: 10;
display: block;
position: absolute;
height: 100%;
top: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.5);
}