Skew background image without distortion? - css

I need to skew the shape of a div that contains a background image, without actually distorting the background image.
Right now I'm using transform: skew(-25deg)
Is it possible to do this without the distortion?

You need to add the background image on a child of the skewed element and then apply an opposite skew to the child. Here's an example:
.parent {
height: 100px;
overflow: hidden;
transform: skew(0.5rad, 0);
width: 100px;
}
.child {
background: linear-gradient(to right, red 0%, blue 100%);
height: 100%;
transform: skew(-0.5rad, 0);
width: 100%;
}
<div class="parent">
<div class="child">
etc.
</div>
</div>

Related

How does centering using absolute positioning and CSS transform work? [duplicate]

This question already has answers here:
How to center a "position: absolute" element
(31 answers)
How can I center an absolutely positioned element in a div?
(37 answers)
Closed 3 years ago.
I learnt a new (new to me) way of centering divs from an online resource. I can not get hold of the author, so please explain what exactly is happening here.
<header class="header">
<div class="header-box">
<h1>
Lorem Ipsum <br>
Dolor sit amet
</h1>
</div>
</header>
.header {
position: relative;
height: 100vh;
background-image: linear-gradient(
to right bottom,
rgba(17, 63, 112),
rgba(253, 135, 31));
background-position: top;
}
.header-box {
position: absolute;
top: 50%; /*This and next line*/
left: 50%;
transform: translate(-50%, -50%); /*and this*/
}
h1 {
text-align: center;
}
How exactly the Transform property is aligning the div in center perfectly when the position property pushed it away?
https://jsfiddle.net/ux1r3eb0/
I'll describe this in the context of horizontal alignment, but exactly the same principles apply to vertical alignment:
The absolute position moves the element's left side to the centre of the screen, then the transform moves the element's centre left by half it's width, which lines up the centre of the element with the centre of the container.
Visual example (I'm only showing the horizontal movement, to make it easier to understand):
.container {
position: relative;
width: 100vw;
height: 100vh;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/AAAZ4gk3AAAACklEQVR4XmNgAAAAAgAB3p6PvwAAAABJRU5ErkJggg==');
background-position: center;
background-size: 1px 100%;
background-repeat: no-repeat;
}
.content {
position: absolute;
width: 100px;
height: 100px;
top: 50%;
border: 1px solid #F00;
animation-name: demo;
animation-duration: 8s;
animation-fill-mode: forwards;
}
#keyframes demo {
0% {
left: 0%;
transform: translate(0%, -50%);
}
50% {
left: 50%;
transform: translate(0%, -50%);
}
100% {
left: 50%;
transform: translate(-50%, -50%);
}
}
<div class="container">
<div class="content"></div>
</div>
The top and left property pushed away the .header-box from the top and left side of .header. 50% value means 50 percent of height and width of .header
while the translate(-50%, -50%) makes the .header-box to pull back itself by half of the size of itself.
When you use percentage in top, left, right, bottom property, it uses the size of closest positioned ancestor element, while the transform uses the size of itself.

CSS transform-origin not working with translate()

I want to move a div from its center point, but it seems that translate() doesn't care what transform-origin is and uses top-left point of the element to move it.
Here is a test to confirm it:
<div class="items" style="">
<div class="item-1" style="width: 100px; height: 100px; background: blue; position: absolute; opacity: 0.5; transform-origin: 0% 0%; transform: translate(100px, 100px)"></div>
<div class="item-2" style="width: 100px; height: 100px; background: red; position: absolute; opacity: 0.5; transform-origin: 100% 100%; transform: translate(100px, 100px)"></div>
</div>
As you can see, bot items are overlapped while it shouldn't.
Question: How to position an element using its center point?
Note: As I'm rotating & moving these items using JS, so just subtracting half of item's width/height is not an option because it needs math that I don't know.

Create angled triangle top and bottom of page

I'm trying to create a diagonal div with SVG and I'm having a lot of issues.
My goal is:
Create full-width map on the top left corner.
Create full-width div of text on the bottom right corner.
I have worked on it but the SVG div overlapping the map and I can't select map and if I position map higher than SVG than map overlaps entire page.
You can see in the image what I want to achieve should look like.
I would use clip-path to do the job. AFAIK it's the only think able to achieve desired effect without JS and without assumption, that rectangle with map is a square. Support, unfortunately, isn't perfect. I also found interesting creator for clip paths.
More about clip-path
The clip-path CSS property creates a clipping region that defines what part of an element should be displayed. More specifically, those portions that are inside the region are shown, while those outside are hidden.
Unfortunetely it doesn't work on IE, but here you can find some fallback workarounds.
Snippet
.container {
position: relative;
height: 250px;
width: 250px;
background: black;
}
.map {
height: 100%;
width: 100%;
background: red;
-webkit-clip-path: polygon(100% 0, 0% 100%, 0 0);
clip-path: polygon(100% 0, 0% 100%, 0 0);
}
.corner {
position: absolute;
right: 0;
bottom: 0;
height: 100%;
width: 100%;
background: green;
-webkit-clip-path: polygon(100% 0, 0% 100%, 100% 100%);
clip-path: polygon(100% 0, 0% 100%, 100% 100%);
}
<div class="container">
<div class="map"></div>
<div class="corner"></div>
</div>

2d transform affect parent only

I'm using transform:matrix on some parent element, but i want that child element is not affected by it.
I've got something like that for parent:
transform:matrix(0.98,-0.53,0.82,0.57,0,0);
-ms-transform:matrix(0.98,-0.53,0.82,0.57,0,0);
-webkit-transform:matrix(0.98,-0.53,0.82,0.57,0,0);
and inside that element is child.
I've tried position:absolute, or fixed for the child, but that doesn't work. I can always reset matrix positions for the child by changing parameters back to normal, but it is not easy to get that exact 100% accurate.
Adding jsfiddle for full code: https://jsfiddle.net/ypvoa8Ly/
Instead of using matrix transformation that can be hard to invert on child element. You can instead use simple transformation in the same property that you can easily invert.
You may also adjust the position of the inner element to avoid some bad overflow:
.img-wrapper {
width: 300px;
height: 300px;
margin:10px auto;
overflow: hidden;
transform: rotate(45deg) skew(-20deg);
position:relative;
}
.img-wrapper img {
transform: skew(20deg) rotate(-45deg);
position:absolute;
top:-15%;
bottom:-15%;
left:-15%;
right:-15%;
}
<div class="img-wrapper">
<img class="main-img" src="http://25.media.tumblr.com/tumblr_m5nre6cxkQ1qbs7p5o1_r1_500.jpg" alt="" />
</div>
Here is also another way to achieve something like this using gradient (since you cannot use clip-path):
.image {
height: 300px;
width: 300px;
margin: auto;
background:
linear-gradient(40deg, #fff 28%, transparent 20%, transparent 75%, #fff 70%),
linear-gradient(-40deg, #fff 28%, transparent 20%, transparent 75%, #fff 20%),
url('http://25.media.tumblr.com/tumblr_m5nre6cxkQ1qbs7p5o1_r1_500.jpg') center/cover no-repeat;
}
<div class="image" ></div>

Set HTML background as two triangles

I am trying to set my HTML background in a way that it looks like it consists of two triangles but I cannot seem to get it to fully fit the page. How would I accomplish that and additionally be able to set a custom color for both?
Here is the code I am working with:
#container {
position: relative;
height: 800px;
width: 800px;
overflow: hidden;
background: grey;
margin-left: -0.4%;
margin-top: -0.4%;
}
#container:before {
content: '';
position: absolute;
left: 28%;
top: 28%;
width: 1200px;
height: 1200px;
background-color: rgb(255, 255, 255); /* fallback */
background-color: rgba(255, 255, 255, 0.5);
-webkit-transition: all 1s;
-moz-transition: all 1s;
transition: all 1s;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
transform: rotate(45deg);
}
<div id="container"></div>
I tried changing all the height and width to 100vh and 100vw but that did not seem to help and there is no option to get the colors changed. Any help would be appreciated!
You can do it with the background: linear-gradient():
html, body {margin: 0; width: 100vw; height: 100vh}
body {
background: -webkit-gradient(linear, left top, right bottom, color-stop(50%, Salmon), color-stop(50%, Khaki));
background: -webkit-linear-gradient(top left, Salmon 50%, Khaki 50%);
background: -o-linear-gradient(top left, Salmon 50%, Khaki 50%);
background: linear-gradient(to bottom right, Salmon 50%, Khaki 50%);
}
http://jsfiddle.net/Liamm12/kkt1kd34/
I hope this what are you looking to do
I just set up the body height:100%; and Width:100%; the page will take the full screen
We should add min-height: 100% to the container it will helps the body to be full screen
And finally I just added padding-bottom to container:after it will makes the design as triangles
html, body {
height: 100%;
width:100%;
margin: 0;
}
#container {
position: relative;
min-height: 100%;
overflow: hidden;
background-color: #645384;
}
#container:after {
content: '';
position: absolute;
padding-bottom: 141.42136%;
left: 30%;
width: 100%;
background-color: #f37638;
-webkit-transition: all 1s;
-moz-transition: all 1s;
transition: all 1s;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
transform: rotate(45deg);
}
<!doctype html>
<html>
<head>
<title></title>
</head>
<body>
<div id="container"></div>
</body>
</html>
In order to answer this question, I have used multiple techniques:
Create the aspect ratio box: This is necessary for second steps (since I need a square for this to work.
For more information, you can look through this: Aspect Ratio Boxed
I have used CSS border triangle in order to provide what you are requesting. Look for more detail here: CSS Triangle
So what I have done is, creating a square box, setting the border to make the arrow. I have also made the jsfiddle for you to look through.
https://jsfiddle.net/vqmjyjhw/
I have also add css variable on top to help you modify the box fast if you need to:
:root {
--width: 100%;
--halfWidth: 242px;
--topColor: red;
--bottomColor: blue;
}
With width variable, you can use %. But in order for the trick to work, halfWidth need to be in px. You can use some extra javascript to calculate exactly what is the width of your container to set halfWidth properly.

Resources