div slanted in 2 directions - css

Is it possible to create the following shape as a DIV in CSS.
The browser support is not important.

You cannot skew an element like this directly, you'll need to use two elements (or generated content) and hide certain overflow to make the flat bottom edge:
http://jsfiddle.net/6DQUY/1/
#skew {
height: 240px;
overflow: hidden;
}
.skew {
background: #000;
display: inline-block;
height: 300px;
width: 500px;
margin-top: 100px;
transform: skew(-8deg, -8deg);
}
Note: I removed the cross browser definitions for better readability.
UPDATE: This would be a more fluid example which resizes in set dimensions: http://jsfiddle.net/6DQUY/3/. Note the padding-bottom on the wrapper which defines the ratio. You may have to play around with the percentage amounts.
#skew {
padding-bottom: 20%;
overflow: hidden;
position: relative;
}
.skew {
background: #000;
position: absolute;
top: 30%;
right: 8%;
left: 8%;
height: 100%;
transform: skew(-8deg, -8deg);
}

Using SVG:
Below is a sample using SVG polygon which can also be scaled easily. Text (if required) can be absolutely positioned on top of the shape.
.shape-svg {
position: relative;
height: 100px;
width: 300px;
}
svg {
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}
polygon {
fill: black;
}
/* Just for demo*/
.shape-svg{
transition: all 1s;
}
.shape-svg:hover {
height: 200px;
width: 600px;
}
<div class="shape-svg">
<svg viewBox='0 0 100 100' preserveAspectRatio='none'>
<polygon points='5,35 100,0 95,100 0,100' />
</svg>
</div>
The shape can be created using SVG clip path also instead of polygon.
Using CSS and Single Element:
The same shape can be achieved with CSS using only one element also. The key is to set the transform-origin as the side that is required to be straight.
.shape{
height: 100px;
width: 300px;
margin-top: 50px;
background: black;
transform-origin: 0% bottom;
transform: perspective(300px) rotateY(-15deg) skewX(-10deg);
transition: all 1s;
}
.shape:hover{
width: 350px;
height: 150px;
transform: perspective(450px) rotateY(-15deg) skewX(-10deg);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="shape"></div>
The shape achieved using this method can also be scaled. However as the height of the shape increases, the right side becomes taller and pushes the top-right corner even more higher. So, either the rotation angle needs to be decreased (or) the perspective needs to be increased (shape needs to be moved farther away) for the height of the right side to remain small enough and be within the viewing area. Or else, the margin-top should be increased.
Below is an explanation on why this happens:
Consider a rectangle positioned 300px in front of the viewer's eye. It is being rotated towards to the viewer and as the rotation happens, the side which is getting closer to the user will appear taller than the other side.
We have fixed the transform origin's x coordinate as 0% and so the height of the left side of the shape would be constant and that of the right side would keep increasing based on the rotation angle.
Because the transform origin's y coordinate is bottom, the bottom side of the shape would be kept straight and any height increase on the right side of the element would be projected upwards resulting in the shape going outside of the screen.
There is no such problem if only the width increases because the rotation angle is too minimal and so the shape's right side will never get anywhere close enough to the viewer to look very tall.
The shape in question is not an exact duplicate of the one discussed here but you can get some more ideas by looking at it :)

You could look into CSS transformations (transform) I have created a JsFiddle with a quick example.
HTML
<div class="skew"></div>
CSS
/* Skew the container one way */
.skew {
background: #000;
display: inline-block;
height: 50px;
width: 500px;
margin-top: 100px;
-webkit-transform: skewY(-5deg);
-moz-transform: skewY(-5deg);
-ms-transform: skewY(-5deg);
-o-transform: skewY(-5deg);
transform: skewY(-5deg);
}
NOTE:
You may need to include other transformations to get the unbalanced look.
--EDIT--
Here is another solution but using :before and :after CSS. JsFiddle.

Related

How do I recreate the Disney Plus / Netflix cover image with CSS?

I have a background image on my website. I want to skew it so that it looks like cover photos on Netflix / Disney Plus (attached below).
Attempt
I tried adding this to my image's CSS, inspired from this question: CSS transform like netflix cover image
transform: rotateY(-30deg) rotateX(40deg) perspective(800px) scale(1.6)
It doesn't produce the desired result, though. Instead it slants incorrectly and doesn't stretch the container entirely.
Code sample
Here is my example: https://jsfiddle.net/gd3wL8nk/11/
Screenshots
Update
I got it to work by adding perspective: 2000px to the containing div, and adding this to the inner div:
transform: rotateY(-20deg) rotateX(20deg) scale(2) translateX(-10%)
My final CSS (with edits for measurement, etc) looked like this:
.container {
height: 90vh;
position: relative;
max-width: 100%;
overflow: hidden;
perspective: 2000px;
height: 900
}
.bg {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 110%;
background-image: url('image-here');
background-size: cover;
transform: rotateY(-20deg) rotateX(20deg) scale(2);
position: absolute;
top: -10%;
left: 0;
minWidth: 800;
}
See fiddle: https://jsfiddle.net/fernandorojo/kr567zp8/4/
You might be looking for transform: skew();!
i.e.
transform: skew(20deg) scale(1.6);
It won't work with both X and Y rotation though. A good method to ensure it's fullscreen is to use the image as a background in an oversized container. For any children items (like the form, if you nest it in the parent div) you will need to apply the opposite skew to ensure it appears without a slant.
If you check the asset Netflix uses, it's been skewed in Photoshop already.

How to make a clipped half circle (D shape) using CSS?

I need help understanding clip-path CSS property in order to make my version of a clipped circle below...
More like the design version:
If you can see on the grey background, my circle appears a lot larger and less round when it's clipped.
What can I do to make a more round circle? My ideas were:
Use clip-path as in the snippet below
Use a pseudo :after element or a right border with radius
Cut a circle image from photoshop and use it as a background image.
Preferably, I'd like to avoid using a background image. However, I need to keep responsiveness in mind as the circle cannot change shapes drastically as we resize the window.
Is clip-path the right way to go? Can someone suggest a simpler and elegant solution with another way using CSS?
Thank you in advance, here's a snippet I wrote that illustrates how I clipped the "green/blue" background:
.page-banner {
background: grey;
width: 100%;
height: 300px;
background-position: top;
overflow: hidden;
}
.page-banner-text {
position: absolute;
background: #00525d8a;
padding-left: 100px;
width: 60%;
/* adjustments to snippet */
top: 10px;
left: 10px;
height: 300px;
/* this is the code for circle */
clip-path: circle(560px at left);
padding-right: 250px;
}
<div class="page-banner">
<div class="container">
<div class="page-banner-text">
<h1 class="block-title">Programs For Adults</h1>
<p>Programs to help children with disabilities in Western MA at all ages and levels of need.</p>
<div id="banner-donate-button">DONATE</div>
</div>
</div>
</div>
Per my comment, instead of using clip path to create your D (which is not supported very well), why not use border radius on your div.
* {
box-sizing: border-box;
}
.page-banner {
position: relative;
background: url(https://www.fillmurray.com/300/900) center center no-repeat;
background-size: cover;
width: 100%;
overflow: hidden; /* hide overflowing bits of circle */
min-height: 300px; /* just give enough height to fit text at smallest screen width size */
}
.circle {
background-color: rgba(50, 108, 116, 0.9); /* use rgba for transparent effect */
color: white;
transform: translate(-50%, -50%); /* move the circle left 50% of it's own width and up 50% of it's own height */
border-radius: 50%;
padding-top: 100%; /* this gives us a responsive square */
position: absolute;
top:50%; /* this vertically centers the circle */
left:0;
width:100%;
min-width:600px; /* this is the miniimum dimensions to allow circle to fill smaller screens */
min-height:600px;
}
.page-banner-text {
position: absolute; /* just positions the text on the right of the cirecle */
left: 50%;
top: 50%;
transform: translateY(-50%);
padding:2em;
width:40%;
}
<div class="page-banner">
<div class="circle">
<div class="page-banner-text">
<h1 class="block-title">Programs For Adults</h1>
<p>Programs to help children with disabilities in Western MA at all ages and levels of need.</p>
<div id="banner-donate-button">DONATE</div>
</div>
</div>
</div>
The only problem with it being responsive though is that as the screen gets wider, the D gets flatter (as the radius extends), but you can combat this by adding a max width and height to the circle div
To anyone looking to solve this with the clip-path property, you have a bit more control with the ellipse clip path. Using the code provided by the OP, I replaced circle with ellipse, and switched to percentages to allow for a slightly better responsive feel.
clip-path:ellipse(67% 100% at 8% 50%);
The first two numbers represent the height and width of the ellipse. The larger the first number, the wider the visible area is. The larger the second number, the wider the height. We're aiming for a D shape, so by adjusting the first number, we can make the D more or less prominent.
This is where the second two numbers, the positioning, comes into play. at 50% 50% centers it. By adjusting the first number, the X positioning, we can move it over where need fit . After playing around with the numbers, you should be able to get the D exactly how you'd like.
.page-banner {
background: grey;
width: 100%;
height: 300px;
background-position: top;
overflow: hidden;
}
.page-banner-text {
position: absolute;
background: #00525d8a;
padding-left: 100px;
width: 60%;
/* adjustments to snippet */
top: 10px;
left: 10px;
height: 300px;
/* this is the code for circle */
clip-path: ellipse(67% 100% at 8% 50%);
padding-right: 250px;
}
<div class="page-banner">
<div class="container">
<div class="page-banner-text">
<h1 class="block-title">Programs For Adults</h1>
<p>Programs to help children with disabilities in Western MA at all ages and levels of need.</p>
<div id="banner-donate-button">DONATE</div>
</div>
</div>
</div>
You could simply use
an inner circle element, which you can achieve with a border-radius equal to half the element's height and width
positioned via position: relative with negative top and left values
inside of an outer bounding box, clipped via overflow: hidden
A simple implementation:
#container {
height: 300px;
width: 100%;
background-color: gray;
overflow: hidden;
}
#circle {
height: 600px;
width: 600px;
background-color: rgba(0, 0, 255, 0.5);
position: relative;
top: -150px;
left: -375px;
}
<div id="container">
<div id="circle"></div>
</div>

What are the calculations behind the properties in a re-rotated element?

I have been playing around with an idea of a contact card type of thing. Apparently hexagons are quite a new trend, but I'd like to keep it a tad simpler, namely: rotated squares. Considering I am quite knowledgeable with HTML and CSS, it wasn't that hard to accomplish this. In a few minutes I came up with this.
HTML
<a href="#" title="Profile of Banana">
<span style="background-image: url(http://s5.favim.com/orig/52/portrait-sigma-50mm-f1.4-hsm-canon-eos-5d-mk2-face-Favim.com-473053.jpg);">
Queen Elizabeth
</span>
</a>
CSS
a {
display: inline-block;
margin: 50px;
width: 150px;
height: 150px;
transform: rotate(45deg);
position: relative;
overflow: hidden;
}
/* Pseudo element for border */
a:after {
content: "";
display: block;
width: 142px;
width: calc(100% - 8px);
height: 142px;
height: calc(100% - 8px);
border: 2px solid white;
position: relative;
z-index: 10;
top: 4px;
left: 4px;
}
/* Span for bg-image and text */
a > span {
display: block;
height: 213px;
width: 213px;
top: -31px;
left: -31px;
position: absolute;
background-size: cover;
background-position: center;
transform: rotate(-45deg);
padding: 76px 24px 0;
}
The idea is quite simple:
Make the link itself a block element, rotated it 45 degrees. Don't forget overflow: hidden
Rotate its child 45 degrees back, apply a background-image to this element (dynamically loaded in my case, therefore inline)
This works in all major browsers and degrades gracefully into a simple square in other browsers (IE8 and below; though you might need a background size polyfill). For this reason I want to keep this HTML structure.
So, what's the problem? First of all I'd like to make it applicable to different sizes where I would only need to set the width and height of the link itself (a) after which the height and width of its child are calculated automatically - in my project I can use the relatively new CSS3 calc() function, if that's of any help, along with the beauty of SASS/SCSS. In other words, I need the ratio between the width of a and its child span. As far as I can tell, it seems that the ratio is the square root of 2: 213 / 150 = 1.42. My first question is, then, why? What's the logic and/or arithmetic behind this? Why can't the span simply take up 100% width of its parent? Why need it be exactly square root 2 times more?
Additionally, I also would like to know where the top and left values come from. I haven't figured out yet which arithmetic might be the base of is. I do know that this might be dependent on the value of transform-origin, but I don't know how exactly. In other words, is it possible with a pre-defined transform-origin value to have top and left to be zero and by doing so removing the need for a per-case calculated value? If not, how can the value of these properties be calculated based on the width value of its parent, as that's the only value that should be known?
Summary, if only the width and height of a are known, how do I:
calculate the width for its child, and how can that be explained?
calculate/use the offsets (top and left) on span and how can they be explained?
I do not want to use any JS solutions for this. If something isn't clear, please post a comment so I can clarify.
UPDATED FIDDLE
First of all, as the background-image defined for span will overlap the actual a element, it needs to be bigger. As we are talking about an angle of 45 degrees, this leads to a triangular cut-off shape in which the size of the main square (i.e. the image) is the long side, and the other two equally-sized lines are of the anchor. Therefore, the size of the image (span) should be equal to sqrt(2)*100% ~= 141.42%.
The positioning of the span then. First we rotate the image back by 45 degrees. Import for this action is that the transform-origin is set to 0 0 rather than 50% 50%. By doing so, the element is rotated around a single point right in the top middle of the rhombus. After rotating it's only a matter of translate the element on the X-axis, which can also be done with CSS transforms: translateX(-50%).
No matter what value is now passed onto a's width and height, the image should always be aligned perfectly within it, with the correct dimensions.
(In the fiddle, try giving a a value of, say, 400px. It looks nice, doesn't it? You can also give nice hover effects to the image.)
a {
display: inline-block;
width: 200px;
height: 200px;
transform: rotate(45deg) translate(50%);
position: relative;
overflow: hidden;
}
a:after {
content: "";
display: block;
width: calc(100% - 8px);
height: calc(100% - 8px);
border: 2px solid white;
position: relative;
z-index: 10;
top: 4px;
left: 4px;
}
a > span {
display: block;
height: 141.42%;
width: 141.42%;
top: 0;
left: 0;
position: absolute;
background-size: cover;
background-position: center;
transform: rotate(-45deg) translateX(-50%);
transform-origin: 0 0;
}

Crop triangle from image in CSS

Our designer wants to do that:
But I can't figure out a good way to do this triangle crop:
With an :after that takes all the width and uses some kind of borders trick to make a triangle
With a big :after element that is rotated and white, but it should not hide any other text
With some magic filter I don't know?
By using a canvas, cropping it in JS, then loading the image as a base64 url? (Maybe overkill :D)
What do you think?
Edit: version 2: http://jsfiddle.net/mtaU8/4/ works with changing bg.
Here ya go: http://jsfiddle.net/mtaU8/
HTML: (I used a div with a background, but you could easily use an img element.)
<div class="container">
<div class="img"></div>
</div>
CSS: (mostly fluff for setup, but basically use transform:rotate() on an :after content, then position it so it slices your picture nicely. Contain all that in your container and you're good to go.)
.container {
width: 250px;
height: 100px;
position: relative;
overflow:hidden;
}
.img {
width: 250px;
height: 100px;
background-color: blue;
position: relative;
}
.img:after{
content:"";
position: absolute;
width: 400px;
height:125px;
background-color: white;
top:90px;
left:-20px;
transform: rotate(5deg);
-moz-transform: rotate(5deg);
-webkit-transform: rotate(5deg);
}
I'd suggest using the CSS clip property:
.crop {
position: absolute;
clip: rect(110px, 160px, 170px, 60px);
}
The clip property's rect value represents the section of the image that will be cropped. Here's a demo.

Off by one pixel issue in IE CSS transform

I am using transform: skew to create the effect of a down arrow on my banner image using both the :before and :after tags. The result should look like the following:
However, in IE 9-11 there seems to be a rounding issue. At some heights there is one pixel from the background image that shows below the skewed blocks resulting in the following:
In my case, the banner is a percentage of the total height of the window. Here is the some sample code which should be able to reproduce the problem:
HTML
<div id="main">
<div id="banner"></div>
<section>
<h1>...</h1>
<p>...</p>
</section>
</div>
CSS
#banner {
position: relative;
background-color: green;
width: 100%;
height: 75%;
overflow: hidden;
}
#banner:before,
#banner:after {
content: '';
display: block;
position: absolute;
bottom: 0;
width: 50%;
height: 1.5em;
background-color: #FFFFF9;
transform: skew(45deg);
transform-origin: right bottom;
}
#banner:after {
right: 0;
transform: skew(-45deg);
transform-origin: left bottom;
}
body {
background-color: #333;
position: absolute;
width: 100%;
height: 100%;
}
#main {
max-width: 40em;
margin: 0 auto;
background-color: #FFFFF9;
position: relative;
height: 100%;
}
section {
padding: 0 1em 5em;
background-color: #FFFFF9;
}
And here a working example.
Yes, seems to be a rounding issue – and I don’t know of anything that one could do to fix this. It’s in the nature of percentage values that they don’t always result in full pixel values – and how rounding is done in those cases is up to the browser vendor, I’m afraid.
I can only offer you a possible workaround (resp. “cover up”) that seems to work – if the layout really is as simple as this, and the main content area has a white background, and no transparency or background-image gets involved there.
Pull the section “up” over the banner by a negative margin of -1px (eliminated top margin of h1 here as well, otherwise it adjoins with the top margin of the section – countered by a padding-top), so that its background simply covers up that little glitch:
section {
padding: 1em 1em 5em;
background-color: #FFFFF9;
position:relative;
margin-top:-1px;
}
section h1:first-child { margin-top:0; }
Well, if you look closely, that makes the corner of triangle look slightly “cut off” (by one pixel) in those situations where the rounding glitch occurs – if you can live with that (and your desired layout allows for it), then take it :-) (And maybe serve it to IE only by some means). If not – then sorry, can’t help you there.

Resources