:before and :after pseudo-elements exhibiting confusing behavior - html

I'm implementing an ::after pseudo-element on an container div. The pseudo element sets a background-color, top 0, left 0, 100% width and height. Inside the div the height is set to 200px. This HTML/CSS combination results in the background-color covering the entire nested div that is enclosed and the added height and width specified.
However, if I remove ::after, the background-color is inserted, but under not on top of the nested div, which seems completely counter-intuitive. Why does using the ::after (or ::before) pseudo-element result in the content covering the nested div, while not using it results in the nested div going on top of the overlay? Shouldn't ::after mean it goes AFTER the content?
.container1 {
position:relative;
height: 100%;
}
.overlay::after {
content: '';
position: absolute;
top: 0;
left: 0;
background-color: hsla(211, 100%, 18%,.6);
z-index: 2;
width: 100%;
height: 100%;
}
#hero {
height: 200px;
background: url(https://preview.ibb.co/nRxrBS/hero_truck_lg.jpg) no-repeat;
}
<div class="container1 overlay">
<div id="hero"></div>
</div>

You've got several items interfering with each other. But I think your main issue is this:
position:absolute; pulls elements out of the render order, causing them to render on top of static elements.

Related

How to make a child div wider than its parent div without covering the surrounding elements

I have a parent div which is basically a very long blog with text and images. I want a div inside it to be wider as the parent, however I don´t want it to cover the surrounding elements. Currently if I do the following it covers the h3 element below it :
.parent{
position: relative;
max-width: 800px;
}
.child{
position: absolute;
left:-17rem
}
Once you add position: absolute you remove it from the document flow, and the rest of the document is rendered as if it doesn't exist - meaning that if it's 20px tall, the content below it will move up 20px to fill that space, since they treat it as if it's not there at all.
The initial overflow value for Box, Grid, and Flex containers is set to visible - so you can position child elements outside of parent elements easily.
Consider using transform and translateX():
.parent {
width: 50%;
max-width: 400px;
}
.child {
width: calc( 100% + 40px ); /* If you want div 40px larger */
transform: translateX(-20px); /* Offset by half of that value (20px) */
}
/* Just Here for Styling Purposes */
.parent{padding:20px 0;margin:0 auto;background:#09e;}.child{background:rgba(0,0,0,.5);color:#fff;padding:10px 0;text-align:center;}.next {background:#eee;padding:20px;text-align:center;}
<div class="parent">
<div class="child">TEXT IN HERE</div>
</div>
<div class="next">This should remain where it was originally</div>

Transformed body fixed-position div aligning to body, not window

I have created a <div> fixed, set the following styles on it:
#mydiv {
position: fixed;
left: -150px;
width: 150px;
top: 0;
bottom: 0;
border: 1px solid #f00;
}
This produces a <div> that is offscreen, and presumably the same height as the window.
Then I apply the following styles to the <body>:
body {
-webkit-transform: translate(150px, 0);
}
To my knowledge, this should move the body 150px to the right, thereby moving #mydiv into view. This works, but now #mydiv is the height of the body, not the height of the window.
Here's a JSFiddle example
Is this a Webkit bug? Or is this something I'm doing wrong?
EDIT:
This appears to happen on Firefox as well.
The solution to this problem, while perhaps not immediately intuitive, is pretty straightforward.
html, body {
height: 100%;
}
Normally position: fixed elements are aligned relative to the window (the parent of the html element). When css transforms are applied, however, position: fixed elements are aligned relative to the closest parent with a css transform applied.
The alternate approach Webkit and other browsers could have taken, would be to still align position: fixed elements to the window. But the problem with this would be the position: fixed div would not move at all when the body was transformed, and so the div would still be positioned offscreen.

How do I handle independent parent and child opacities when the child element is a link?

I have a parent <div> and a child <a>. The parent has a background image set to 60% opacity, but I'd like the child link to have 100% opacity. My reason for implementing it this way is so I can fade the parent's opacity to 100% on hover, thereby eliminating the need for a hover image.
I understand that children inherit their parent's opacity. I tried the :after {} technique described here, but even with appropriate z-index values set, the child link still sits beneath the parent element and is not clickable.
My issue is that the child link cannot be clicked because the parent's :after pseudo-element sits above the child.
My code is as follows:
<div>
Load more
</div>
div {
position: relative;
height: 300px;
}
div:after {
position: absolute;
top: 0;
left: 0;
content: '';
background: url('../img/bg-load-more.png') repeat-x;
width: 100%;
height: 300px;
z-index: 10;
opacity: 0.4;
}
div a {
display: block;
z-index: 100;
}
Does anyone know of a solution to this issue, or must I create an image sprite and switch swap background images on hover?
The problem is that you aren't applying a position to the <a> itself (z-index only applies to positioned elements) only the containing div and the pseudo-element, so the pseudo-element is sitting on top of the link preventing it from being clicked.
All you need to do is give the link a stacking context, e.g. include relative positioning:
div a {
display: block;
position: relative;
z-index: 100;
}
Example

Is there a foreground equivalent to background-image in css?

I want to add some shine to an element on webpage. I would prefer if I don't have to add additional html to the page. I want the image to appear in front of the element rather than behind. What's the best way to do this?
To achieve a "foreground image" (without extra HTML code), you can use a pseudo-element (::before / :before) plus the CSS pointer-events. The last property is needed so that the user can actually click through the layer "as if it did not exist".
Here's an example (using a colour whose alpha channel is 50% so that you can see that the real elements can actually be focused). http://jsfiddle.net/JxNdT/
#cont {
width: 200px;
height: 200px;
border: 1px solid #aaa;
/*To show the boundaries of the element*/
}
#cont:before {
position: absolute;
content: '';
background: rgba(0, 0, 0, 0.5);
width: 200px;
height: 200px;
pointer-events: none;
}
<div id="cont">
Test<br>
<input type="text" placeholder="edit">
</div>
​
PS. I picked the ::before pseudo-element, because that naturally leads to the correct positioning. If I pick ::after, then I have to add position:relative; to the real element (#cont), and top:0;left:0; to the pseudo-element (::after).
PPS. To get the foreground effect on elements without a fixed size, an additional element is needed. This wrapper element requires the position:relative;display:inline-block; styles. Set the width and height of the pseudo-element to 100%, and the pseudo-element will stretch to the width and height of the wrapper element. Demo: http://jsfiddle.net/JxNdT/1/.
If you need a white-transparent foreground
This is for future visitors like me who are considering adding a white-transparent foreground to an element to communicate that it's hidden / disabled for instance. You can often achieve your goal by simply lowering the opacity below 1:
.is-hidden {
opacity: 0.5;
}
visible
<span class="is-hidden">hidden</span>
visible
You can use this css
#yourImage
{
z-index: 1;
}
NOTE
Set the z-index to index greater the the z-index of the element over which you are putting the image.
If you have not specified any z-index then 1 would do the work.
You can also set z-index to -1,in that case the image would always be at background!
A neat solution: box-sizing + padding-left, see more at css-tricks
Somewhere in your HTML:
<img id="test_replacement" src="test.png" alt="test" />
The CSS for replacing the image (on hovering)
#test_replacement {
width: 200px; //must be the size of your image (and the replacement one)
height: 200px; //idem
display: block;
}
#test_replacement:hover {
box-sizing: border-box;
background-image: url('somewhere/other_image.png');
padding-left: 200px; //at least the size of the width
}
Use an absolutely positioned <img> element:
img {
position: absolute;
opacity: 0.3;
pointer-events: none;
}
iframe {
width: 500px;
height: 300px;
border: 0;
}
<img src="https://i.stack.imgur.com/rET57.jpg" alt="Foreground image">
<iframe src="https://example.com/"></iframe>

Div on top of Div using z-index

I have the following divs in my HTML:
<div class="main">
<div class="bgimage"></div>
<div class="content">Text</div>
which is directly inside my body.
With the following CSS:
body {
margin: 0;
padding: 20px 0;
}
.content {
filter: alpha(opacity=50);
-moz-opacity: 0.5;
opacity: 0.5;
}
.content {
position: relative;
z-index: 1;
border: #000 thin solid;
width: 960px;
margin-left: auto;
margin-right: auto;
background-color: #000;
}
.bgimage {
position: absolute;
z-index: -1;
width: 1024px;
height: 768px;
margin-left: auto;
margin-right: auto;
background-image: url(bg1.jpg);
}
Basically, I have a Div that with a display of a background image, and I will have another Div on top of this with transparency. This current code works, but my problem is when I am trying to take the content div down from the top.
When I add margin-top:100px, for example, is also brings the image down. I thought it would not touch it if it is not on the same z-index? Why does adding a margin also force the bgimage div down?
I have also tried making the div with class of content a position of absolute and a zindex, but then this won't centre. How should I solve this?
your CSS should be
.bgimage { position: relative; }
.content { position: absolute; }
so the .content will be positioned relative to the .bgimage
your current CSS makes the .bgimage position relative to the document.
see this link on CSS positioning
z-index has no relation to positioning: it only affects the rendering order of your elements. Position: relative tells the browser to render the element at the place it should be, and offset it by eventual left, right, top or bottom coordinates. Therefore, margins, paddings, etc. still affect it.
Only position: absolute guarantees position independance.
I see no need for "z-index"es or "position: absolute" in your code at all -- unless you have other complications that you have not revealed to us.
To center the background on the DIV class="main":
body{margin:0;padding:20px 0;}
.main{background:transparent url(bg1.jpg) no-repeat center top;}
.content{border:#000 thin solid;width:960px;margin-left:auto;margin-right:auto;background-color:#000;opacity: 0.5;filter:alpha(opacity=50);-moz-opacity: 0.5;}
The "center top" places the center-top of the background image on the center-top of the element it's applied to. You may want to apply a
min-width:1024px;_width:1024px;
to the same element -- to prevent a narrower window from hiding the edges (this will change how the element is rendered if the "viewport" is narrower than the background's dimensions).
The only thing your pre-modified code it can do that my modified code can't:
Crop the background image (if it is not natively 1024px x 768px) by using the css "width" and "height" properties
If the class="main" element already has a background image set, most browsers don't support the CSS3 required to stack multiple backgrounds on the same element
Some of what was stated about "z-indexing" and the "position" property above was correct but failed to mention:
you've taken your class="content" element out of "the flow". The ancestor elements won't grow when the content of class="content" element grows. This is an important and fundamental difference between "z-index"ed elements and elements that remain "in the flow".
Other side notes:
elements with the same z-index are stacked according to their order in the HTML (later in the HTML means they are drawn above on the screen)
"z-index"ing requires "position: (absolute|relative)", "z-index: (valid value)", and IIRC "(top|left|bottom|right): (valid value)" to take the element "out of the flow"
CSS absolute positioning is always done "relative" to the most recent ancestor that has a "position: relative", otherwise it uses the body tag by default. If the CSS you included is all that affects those divs, then your .content div will be positioned relative to the .main div, but your .bgImage will be positioned based on the tag.
If you want both .content and .bgImage to move in lockstep, then you'll need to add a "position: relative" to div.main.