Reputation: 464
I need to create a mask to overlay an image in all browsers based on vh
(no clip-path
)
I'm using a div with a rotational transform as a mask, then on the inner reversing the rotation.
The issue I'm having is content inside of the inner isn't positioning correctly. The image needs to be aligned to top left of the inner container.
I have tried:
https://jsfiddle.net/owfgLnv7/5/
.container {
width: 70vh;
height: 100vh;
background-color: blue;
position: absolute;
left: 0;
top: 0;
z-index: 0;
}
.tri {
position: absolute;
width: 70vh;
height: 70vh;
transform: rotate(45deg);
top: calc((100vh - 70vh) / 2);
transform-origin: center center;
background-color: transparent;
z-index: 2;
overflow: hidden;
}
.reset-tri {
position: relative;
z-index: 1;
transform: rotate(-45deg);
transform-origin: center center;
}
.inner-container {
background: black;
}
Need to get the image so that it is top left aligned and flowing normally
Upvotes: 3
Views: 98
Reputation: 42352
Basically, when elements are transformed (rotated here), they are taken out of the flow - so dimensions won't behave as it does when you don't.
One approach is just using simple mathematics:
a
, then the diagonal will be √2 * a
~ 1.414 * a
,transform-origin
is center
here, this means you have the overflowing width or height equal to (1.414 * a - a) / 2
or (1.414 - 1) * a / 2
.container
which will have a width equal to width: calc(1.414 * 70vh)
See demo below:
body {
margin: 0;
}
.page {
width: 100vw;
height: 100vh;
background: grey;
}
.container {
width: calc(1.414 * 70vh); /* changed */
height: 100vh;
background-color: blue;
position: absolute;
left: 0;
top: 0;
z-index: 0;
}
.tri {
position: absolute;
width: 70vh;
height: 70vh;
transform: rotate(45deg);
top: calc(0.414 * 70vh / 2); /* changed */
left: calc(0.414 * 70vh / 2); /* added */
transform-origin: center center;
background-color: transparent;
z-index: 2;
overflow: hidden;
}
.reset-tri {
position: relative;
z-index: 1;
transform: rotate(-45deg);
transform-origin: center center;
}
.inner-container {
background: black;
}
<div class="page">
<div class="container">
<div class="tri">
<div class="reset-tri">
<div class="inner-container">
<img src="https://openclipart.org/download/230732/360sj3.svg" />
</div>
</div>
</div>
</div>
</div>
Using Background Image
For a near-perfect masking you can:
move the image
to a background-image
in the reset-tri
container and
add a scale(1.414)
transform to exactly fill the original un-transformed tri
container.
See demo below:
body {
margin: 0;
}
.page {
width: 100vw;
height: 100vh;
background: grey;
}
.container {
width: calc(1.414 * 70vh); /* changed */
height: 100vh;
background-color: blue;
position: absolute;
left: 0;
top: 0;
z-index: 0;
}
.tri {
position: absolute;
width: 70vh;
height: 70vh;
transform: rotate(45deg);
top: calc(0.414 * 70vh / 2); /* changed */
left: calc(0.414 * 70vh / 2); /* added */
transform-origin: center center;
background-color: transparent;
z-index: 2;
overflow: hidden;
}
.reset-tri {
position: relative;
z-index: 1;
transform: rotate(-45deg) scale(1.414); /* scale by √2 */
transform-origin: center center;
width: 70vh;
height: 70vh;
/* use a bacground image */
background-size: cover;
background-image: url("https://openclipart.org/download/230732/360sj3.svg");
}
<div class="page">
<div class="container">
<div class="tri">
<div class="reset-tri"></div>
</div>
</div>
</div>
Using Image Element
For a near-perfect masking without using background-image
you can go back to the previous markup and add object-fit: cover
to the img
element that fills the dimensions of its wrapper, the inner-container
- see demo below:
body {
margin: 0;
}
.page {
width: 100vw;
height: 100vh;
background: grey;
}
.container {
width: calc(1.414 * 70vh); /* changed */
height: 100vh;
background-color: blue;
position: absolute;
left: 0;
top: 0;
z-index: 0;
}
.tri {
position: absolute;
width: 70vh;
height: 70vh;
transform: rotate(45deg);
top: calc(0.414 * 70vh / 2); /* changed */
left: calc(0.414 * 70vh / 2); /* added */
transform-origin: center center;
background-color: transparent;
z-index: 2;
overflow: hidden;
}
.reset-tri {
position: relative;
z-index: 1;
transform: rotate(-45deg) scale(1.414); /* scale by √2 */
transform-origin: center center;
width: 70vh;
height: 70vh;
}
.inner-container {
height: 100%; /* fill the parent wrapper */
}
.inner-container > img {
width: 100%;
height: 100%;
object-fit: cover; /* the image fills the parent container */
}
<div class="page">
<div class="container">
<div class="tri">
<div class="reset-tri">
<div class="inner-container">
<img src="https://openclipart.org/download/230732/360sj3.svg" />
</div>
</div>
</div>
</div>
</div>
Upvotes: 2