Div Backgrounds That Overlap At The Corner - html

There are several separate background images, displayed top to bottom. Is it possible to make them overlap slightly and clip a transparent triangular area in the bottom-right corner revealing the image below?
Is this possible with CSS?
Here is the desired look:

Yes, this is very possible with CSS.
Here is a technique using a rotated div and :before pseudo element. This looks like a long explanation, but the basic principal is pretty straight forward once you start poking around.
Compatibility: IE9 + and all modern browsers — The transform property in IE9 requires the -ms- prefix and Safari requires the -webkit- prefix. They should be placed before the unprefixed property.
The wrapper
The wrapper is used to clip the slanted corners of each div.
Provide a suitable max and min width
Clip its children with overflow: hidden
The div
The div is used to create the slant by clipping its childrens bottom right corner.
Rotate with transform: rotate()
Clip its children with overflow: hidden
Blow the width out with width: 200% so that the corners are clipped by the wrapper
Move every div (except the first div) up with a negative margin
Change the z-order with z-index so that each div is overlapped by the div before it
The :before pseudo element
The :before provides the actual background image without any extra markup.
Counter the div parents rotation by the same number of degrees
Provide the background image
Shift as needed with transform-origin
The straight edge is provided by the bottom edge of the image and the corner is cut off by the parent. The image must be quite large to overlap the width of its parent.
Full Example
Example with prefixes.
.wrap {
margin: 0 auto;
max-width: 1000px;
min-width: 660px;
overflow: hidden;
background: #EEE;
}
.wrap > div {
transform: rotate(-15deg);
height: 700px;
width: 200%;
overflow: hidden;
transform-origin: 0 90%;
position: relative;
z-index: 10;
}
.wrap > div:before {
content: '';
display: block;
width: 100%;
height: 100%;
background: url(http://lorempixel.com/output/food-q-c-1500-1000-2.jpg) no-repeat;
transform: rotate(15deg);
position: absolute;
transform-origin: 30% 0;
}
.wrap > div:nth-child(n+2) {
margin-top: -140px;
}
.wrap > div:nth-child(2):before {
background-image: url(http://lorempixel.com/output/people-q-c-1500-1000-10.jpg);
}
.wrap > div:nth-child(3):before {
background-image: url(http://lorempixel.com/output/technics-q-c-1500-1000-3.jpg);
}
.wrap > div:nth-child(2) {
z-index: 9;
}
.wrap > div:nth-child(3) {
z-index: 8;
}
<div class="wrap">
<div></div>
<div></div>
<div></div>
</div>

Related

CSS image and pseudo element transition out-of-sync

I'm trying to create a transition for both an image and a pseudo element of its container, but for some reason, these transitions appear to be out of sync with each other, resulting in the pseudo element reaching a opacity: 0 state before the image does.
I've tried various combinations of style rules, but I never managed to accomplish an ease-in-out transition to work correctly.
Here's some context for the current code: the image is padded on purpose, to provide a better visual (centered) of its content. The images that'll be used are always guaranteed to have a white background. That's why I'm using a pseudo-element with a white background color to fill the vertical spaces that the image does not cover.
The background-image should take the full width/height of the container and there are not guarantees of its background being white.
The desired effect is for both the pseudo-element and image to reach opacity: 0 at the same making it look like its a single element.
I'm also considering using an ::after pseudo element to provide a "loading skeleton" while the image is not retrieved from the server, but that's not a concern for now.
Here's the code, and the respective fiddle: https://jsfiddle.net/rjk2z31d/1/
*,
*::before,
*::after {
box-sizing: border-box;
}
.box {
width: 248px;
height: 320px;
}
.image-box {
position: relative;
display: block;
background-repeat: no-repeat;
background-size: cover;
line-height: 0;
background-color: #FFFFFF;
&::before {
display: block;
content: "";
width: 100%;
padding-top: (100% + (100% / 3));
}
img {
z-index: 1;
position: absolute;
top: 50%;
left: 0;
width: 100%;
transform: translate3d(0, -50%, 0);
padding: 16px 16px;
}
&::before, img {
background-color: #FFFFFF;
opacity: 1;
transition: all 1.5s ease-in-out;
}
&:hover {
&::before, img {
opacity: 0;
}
}
}
<div class="box">
<div class="image-box" style="background-image: url('https://via.placeholder.com/248x320/FF0000/000000?text=Background')">
<img src="https://via.placeholder.com/248x320/FFFFFF/000000?text=Image">
</div>
</div>
Actually, they both fade at the same speed.
The out-of-sync effect you're talking about is an illusion due to the opacities overlapping.
If you set the initial opacity of both elements, it's easier to understand what's going on.
The image's faded white added to the pseudo element's faded white looks less transparent than the pseudo element's faded white alone.
See it in effect with the below image:
If you need to be convinced of their synchronization, add a transform rule to the :hover handler. the result is synced as it is supposed to be.
As a workaround, I would suggest you to try figuring out a better approach than fading overlapping elements.
You could use the <picture> tag with css object-fit property to get rid of those blank spaces.
picture doc
object-fit doc

:before and :after pseudo-elements exhibiting confusing behavior

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.

Container transformed to fit, positioned absolute, still causing overflow as if not transformed

Edit: I had forgot to mention that I also had it positioned absolute. Absolutely sorry for that. Edits in content are in bold.
I have this container that I use for scaling its contents. I needed to scale things down evenly, and realized that I could use transform CSS attribute for my convenience.
The result is good, the contents are scaled and placed nicely. The problem is, I get overflow on the body element, caused by the container element. It is not crossing the window borders, not when its transformed, and is positioned absolute. However, for some reason, my browser (Edge 16) decides to accommodate space for the element as if it was not transformed.
.container {
position: absolute;
width: 10000px; height: 10000px;
border: solid 100px red;
transform-origin: top left;
transform: scale(0.01);
}
.orange-box {
width: 5000px; height: 2000px;
background-color: orange;
}
<div class='container'>
<div class='orange-box'>
</div>
I have tried it a couple of times on Chrome 64, I don't get overflows on body there. I do want to make use of this, though, and I want to have Edge support.
Is there a way to get around of this bug/issue? Is there, perhaps, a way to prevent specific elements from causing overflow, without completely hiding them? I don't want to overflow: none on the body, either, since the body might legitimately be overflowing.
I don't think it's a bug in Edge. At least, I see scrollbars in Chrome.
May be you can get around it placing the div far to the left and top (that don't stretch the body boundaries)
.container {
width: 10000px;
height: 10000px;
border: solid 100px red;
transform: scale(0.01);
top: -10095px;
position: absolute;
left: -10095px;
transform-origin: right bottom;
}
.orange-box {
width: 5000px; height: 2000px;
background-color: orange;
}
<div class='container'>
<div class='orange-box'>
</div>
I encapsulated it all inside another container, positioned it as relative, transformed it with translate(0). Transformation does nothing, but it is different than none, which is all I need to have a child positioned as fixed to respect its container's position: See MDN/position/fixed
Then, I have changed the positioning of our former container to fixed, which did what the absolute couldn't do on Edge 16, and removed the container from the document flow.
.container-container {
position: relative;
top: 50px;
transform: translate(0);
}
.container {
position: fixed;
width: 10000px; height: 10000px;
border: solid 100px red;
transform-origin: top left;
transform: scale(0.01);
}
.orange-box {
width: 5000px; height: 2000px;
background-color: orange;
}
<div class='container-container'>
<div class='container'>
<div class='orange-box'>
</div>
</div>
I positioned the container-container away from the top left, to show that the fixed child moves along with it, thanks to the translate(0) transform.
However, I didn't use this. I instead styled the container-container to have its overflow as hidden via CSS, and left everything as before. This works out only if the container-container has width and height set to be contained within the body, which was already the case in my application.

CSS image hover pushes other elements in the page?

When the image grows in hover to 350px it pushes everything around.
This code is working except that when I hover and the picture grows it pushes the menu or what ever is around downwards.
How can I stop this?
#displaycar img
{
height: 200px;
}
#displaycar img:hover
{
height: 350px;
}
BTW I'm using twitter bootstrap and I have tried position: absolute;.
Is there any way to still increase size when hover but don't push nothing don't move nothing.
Set the height of #displaycar (the presumed parent div) to 200px and add overflow: visible;
#displaycar {
height: 200px;
overflow: visible;
}
I would use z-index on the elements. keep the values equal on the initial layout, but make it a stronger (bring to front) value when hovering
#displaycar img:hover
{
z-index:[stronger value];
height: 350px;
position :[relative, absolute, fixed];
}
note: to use z-index, you have to use one of the position values
Z-index gives priority to overlapping elements (bring to front / bring to back)
here is a bit more info on the subject
It's possible, but to avoid affecting surrounding content the element itself has to be removed from the flow of the document; this is easiest to achieve using position: absolute, though unfortunately this requires using a wrapping element, with position: relative (or any other non-static position value). The wrapping element has to have a width and height defined, which could be done automatically (with JavaScript, or PHP (amongst many other options)).
For example, the HTML:
<span>
<img src="http://placekitten.com/400/400/" />
</span>
<p><!-- generic dummy content, excised for brevity --></p>
And the CSS:
span {
display: inline-block;
position: relative;
width: 150px;
height: 150px;
}
span img {
position: absolute;
top: 0;
left: 0;
height: 150px;
width: 150px;
/* Vendor-prefixes removed, for brevity */
transition: all 1s linear;
}
span:hover img {
width: 400px;
height: 400px;
/* Vendor-prefixes removed, for brevity */
transition: all 1s linear;
}
JS Fiddle demo.

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>