Related
We are using the code from the below link.
https://codepen.io/s-gupta/pen/jOMGbMX
body {
background: #333;
font-family: "SF UI Text", "Avenir", "Helvetica", arial, san-serif;
color: #888;
}
.ccdLogo {
background: url("https://crystalcleardesigns.co.uk/img/CCDlogo.svg") no-repeat center / 100%;
height:100px;
width:150px;
position: absolute;
bottom: 0;
right: 0;
}
.ccdLogo:before {
content: "Click to view more pens";
color:transparent;
font-size:14px;
position: absolute;
top:-2px;
left:5px;
transition:0.4s;
}
.ccdLogo:hover:before {
color:#2B7B9B;
transform: translateY(-10px);
}
.wrapper {
margin: 5vh auto 0;
}
.pyramid {
float: left;
shape-outside:polygon(310px 0px, 130px 405px, 558px 405px);
padding-right:60px;
width: 500px;
height:500px;
}
.zone {
padding:40px 0;
margin: 0 auto;
text-align:center;
color: black;
background-blend-mode:darken;
transition: 0.5s;
}
.zone:nth-child(1){
background:rgba(202,197,95,0.7) url("https://pixabay.com/static/uploads/photo/2016/01/05/13/34/laugenbrotchen-1122509_960_720.jpg") center / cover;
width: 25%;
clip-path:url("#part1");
clip-path:polygon(50% 0%,100% 100%, 0% 100%);
-webkit-clip-path:polygon(50% 0%,100% 100%, 0% 100%);
}
.zone:nth-child(2){ background: rgba(202,197,95,0.7) url("https://pixabay.com/static/uploads/photo/2016/01/27/14/22/orange-1164504_960_720.jpg") center / cover;
width: 50%;
clip-path:url("#part2");
clip-path:polygon(25% 0%,75% 0, 100% 100%,0% 100%);
-webkit-clip-path:polygon(25% 0%,75% 0, 100% 100%,0% 100%);
}
.zone:nth-child(3){
width: 75%;
background:rgba(202,197,95,0.7) url("https://pixabay.com/static/uploads/photo/2015/11/21/18/07/apple-juice-1055331_960_720.jpg") center /cover;
clip-path:url("#part3");
clip-path:polygon(16.5% 0, 83% 0, 100% 100%,0% 100%);
-webkit-clip-path:polygon(16.5% 0, 83% 0, 100% 100%,0% 100%);
}
.zone:nth-child(4){
background:rgba(202,197,95,0.7) url("https://pixabay.com/static/uploads/photo/2016/01/17/04/29/rain-drops-1144448_960_720.jpg") center / cover;
width: 100%;
clip-path:url("#part4");
clip-path:polygon(12.5% 0, 0%,87.5% 0, 100% 100%,0% 100%);
-webkit-clip-path:polygon(12.5% 0,87.5% 0, 100% 100%,0% 100%);
}
.zone:hover {
background-color: rgba(255,255,255,0.3);
color: white;
}
<div class="wrapper">
<div class="pyramid">
<div class="zone">Triangle more text..</div>
<div class="zone">Trapezoid</div>
<div class="zone">Trapezoid</div>
<div class="zone">Trapezoid</div>
</div>
<h1 class ="text">Oh, the Places You'll Go!</div>
<p class ="text">Congratulations! <br>
Today is your day.<br>
You're off to Great Places!<br>
You're off and away!<br>
<br>
You have brains in your head.<br>
You have feet in your shoes.<br>
You can steer yourself <br>
any direction you choose.<br>
You're on your own. And you know what you know.<br>
And YOU are the guy who'll decide where to go.<br>
<br>
You'll look up and down streets. Look 'em over with care.<br>
About some you will say, "I don't choose to go there."<br>
</div>
<svg width="0" height="0">
<defs>
<clipPath id="part1" clipPathUnits= "objectBoundingBox">
<polygon points= "0.5 0, 1 1, 0 1"/>
</clipPath>
<clipPath id="part2" clipPathUnits= "objectBoundingBox">
<polygon points= "0.25 0,0.75 0, 1 1, 0 1"/>
</clipPath>
<clipPath id="part3" clipPathUnits= "objectBoundingBox">
<polygon points= "0.165 0,0.83 0, 1 1, 0 1"/>
</clipPath>
<clipPath id="part4" clipPathUnits= "objectBoundingBox">
<polygon points= "0.125 0,0.875 0, 1 1, 0 1"/>
</clipPath>
</defs>
</svg>
Issue: The long text hides outside the div with style -webkit-clip-path.
How can we show the text even outside the triangle?
Any help is highly appreciated :)
Thanks in advance.
Some code snippet but please refer to the link for complete code.
<div class="pyramid">
<div class="zone">Triangle more text..</div>
<div class="zone">Trapezoid</div>
<div class="zone">Trapezoid</div>
<div class="zone">Trapezoid</div>
.zone:nth-child(1){
background:rgba(202,197,95,0.7) url("https://pixabay.com/static/uploads/photo/2016/01/05/13/34/laugenbrotchen-1122509_960_720.jpg") center / cover;
width: 25%;
clip-path:url("#part1");
clip-path:polygon(50% 0%,100% 100%, 0% 100%);
-webkit-clip-path:polygon(50% 0%,100% 100%, 0% 100%);
}
You need to have the text inside of a different element. You could wrap the text in a span and then have another empty span after it (but still within zone). Apply the background and clip to the empty span.
You'd need to share more code to get a more specific response.
Move the background part to pseudo elements:
body {
background: #333;
font-family: "SF UI Text", "Avenir", "Helvetica", arial, san-serif;
color: #888;
}
.ccdLogo {
background: url("https://crystalcleardesigns.co.uk/img/CCDlogo.svg") no-repeat center / 100%;
height: 100px;
width: 150px;
position: absolute;
bottom: 0;
right: 0;
}
.ccdLogo:before {
content: "Click to view more pens";
color: transparent;
font-size: 14px;
position: absolute;
top: -2px;
left: 5px;
transition: 0.4s;
}
.ccdLogo:hover:before {
color: #2B7B9B;
transform: translateY(-10px);
}
.wrapper {
margin: 5vh auto 0;
}
.pyramid {
float: left;
shape-outside: polygon(310px 0px, 130px 405px, 558px 405px);
padding-right: 60px;
width: 500px;
height: 500px;
}
.zone {
padding: 40px 0;
margin: 0 auto;
text-align: center;
color: black;
background-blend-mode: darken;
transition: 0.5s;
position:relative;
z-index:0;
}
.zone::before {
content:"";
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
z-index:-1;
}
.zone:nth-child(1) {
width: 25%;
}
.zone:nth-child(1)::before {
background: rgba(202, 197, 95, 0.7) url("https://pixabay.com/static/uploads/photo/2016/01/05/13/34/laugenbrotchen-1122509_960_720.jpg") center / cover;
clip-path: url("#part1");
clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
-webkit-clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
}
.zone:nth-child(2) {
width: 50%;
}
.zone:nth-child(2)::before {
background: rgba(202, 197, 95, 0.7) url("https://pixabay.com/static/uploads/photo/2016/01/27/14/22/orange-1164504_960_720.jpg") center / cover;
clip-path: url("#part2");
clip-path: polygon(25% 0%, 75% 0, 100% 100%, 0% 100%);
-webkit-clip-path: polygon(25% 0%, 75% 0, 100% 100%, 0% 100%);
}
.zone:nth-child(3) {
width: 75%;
}
.zone:nth-child(3)::before {
background: rgba(202, 197, 95, 0.7) url("https://pixabay.com/static/uploads/photo/2015/11/21/18/07/apple-juice-1055331_960_720.jpg") center /cover;
clip-path: url("#part3");
clip-path: polygon(16.5% 0, 83% 0, 100% 100%, 0% 100%);
-webkit-clip-path: polygon(16.5% 0, 83% 0, 100% 100%, 0% 100%);
}
.zone:nth-child(4) {
width: 100%;
}
.zone:nth-child(4)::before {
background: rgba(202, 197, 95, 0.7) url("https://pixabay.com/static/uploads/photo/2016/01/17/04/29/rain-drops-1144448_960_720.jpg") center / cover;
clip-path: url("#part4");
clip-path: polygon(12.5% 0, 0%, 87.5% 0, 100% 100%, 0% 100%);
-webkit-clip-path: polygon(12.5% 0, 87.5% 0, 100% 100%, 0% 100%);
}
.zone:hover {
color: white;
}
.zone:hover::before {
background-color: rgba(255, 255, 255, 0.3);
}
<div class="wrapper">
<div class="pyramid">
<div class="zone">Triangle more text..</div>
<div class="zone">Trapezoid</div>
<div class="zone">Trapezoid</div>
<div class="zone">Trapezoid</div>
</div>
<h1 class="text">Oh, the Places You'll Go!</div>
<p class="text">Congratulations! <br> Today is your day.<br> You're off to Great Places!<br> You're off and away!<br>
<br> You have brains in your head.<br> You have feet in your shoes.<br> You can steer yourself <br> any direction you choose.<br> You're on your own. And you know what you know.<br> And YOU are the guy who'll decide where to go.<br>
<br> You'll look up and down streets. Look 'em over with care.<br> About some you will say, "I don't choose to go there."<br>
</div>
<svg width="0" height="0">
<defs>
<clipPath id="part1" clipPathUnits= "objectBoundingBox">
<polygon points= "0.5 0, 1 1, 0 1"/>
</clipPath>
<clipPath id="part2" clipPathUnits= "objectBoundingBox">
<polygon points= "0.25 0,0.75 0, 1 1, 0 1"/>
</clipPath>
<clipPath id="part3" clipPathUnits= "objectBoundingBox">
<polygon points= "0.165 0,0.83 0, 1 1, 0 1"/>
</clipPath>
<clipPath id="part4" clipPathUnits= "objectBoundingBox">
<polygon points= "0.125 0,0.875 0, 1 1, 0 1"/>
</clipPath>
</defs>
</svg>
Unfortunately, you can't.
The first thing it comes to my mind is to use a wrapper and to put inside it two different divs, one for the text and one for the shape. After that, play with the positioning thanks to margins, negative padding, left, top, absolute/relative and so on
The image is the grandparent div, the black translucent overlay is the parent div, and the cropped section is the child div. User will see the grandparent image and the parent overlay, then he can crop through it using the child cropper div. I tried and failed with opacity and rgba background.
These crazy approaches do seem to work for me -
Set the grandparent image in the background of the child div as well and then change the x/y of the background-position.
Combine child and parent into one single div, and use rgba border as the overlay (my friend's suggestion).
Found this on stackoverflow, which uses box-shadow instead of borders and seems like a similar approach to #2.
My minor gripe with #2 and #3 is that I'll need to add another div for the dashed borders so the user clearly knows what he's cropping. But my bigger gripe with all of them is that none of these looks like the right approach.
Is there a proper / better / 2018-ish / "its so obvious, you idiot" way to do this?
Update: Here's the basic markup (I am okay with a different markup too if that helps in solving this)
#grandparentImage {
background: url(https://9to5mac.com/wp-content/uploads/sites/6/2018/07/Desert-2.jpg) no-repeat;
background-size: cover;
position: relative;
height: 500px;
}
#parentOverlay {
background: rgba(0,0,0,0.5);
height: 100%;
position: relative;
}
#childCropper {
border: 1px dashed #ccc;
left: 50px;
height: 100px;
width: 100px;
position: absolute;
top: 50px;
}
<div id="grandparentImage">
<div id="parentOverlay">
<div id="childCropper"></div>
</div>
</div>
Edit: It is not a duplicate of the marked question, since that question deals with how to grab the cropped image, this one deals with how to show the user what he's cropping. More about UI than data.
You can set box-shadow with 100vmax spread radius on the #childCropper. In this way it will always cover the screen:
#grandparentImage {
background: url(https://9to5mac.com/wp-content/uploads/sites/6/2018/07/Desert-2.jpg) no-repeat;
background-size: cover;
position: relative;
height: 500px;
}
#childCropper {
position: absolute;
top: 50px;
left: 50px;
height: 200px;
width: 200px;
border: 1px dashed #ccc;
box-shadow: 0 0 0 100vmax rgba(0,0,0,0.5);
}
body {
margin: 0;
}
<div id="grandparentImage">
<div id="childCropper"></div>
</div>
This seems like a perfect job for pseudo-elements. So this solution is an upgrade of #2 suggestion in the question, but instead of using the element itself, it uses :after:
#grandparentImage {
background: url(https://upload.wikimedia.org/wikipedia/commons/thumb/e/e5/%D0%94%D0%B7%D0%B5%D0%BC%D0%B1%D1%80%D0%BE%D0%BD%D1%8F._%D0%9F%D0%B5%D1%80%D0%B2%D1%8B%D0%B5_%D0%BB%D1%83%D1%87%D0%B8_%D1%81%D0%BE%D0%BB%D0%BD%D1%86%D0%B0.jpg/800px-%D0%94%D0%B7%D0%B5%D0%BC%D0%B1%D1%80%D0%BE%D0%BD%D1%8F._%D0%9F%D0%B5%D1%80%D0%B2%D1%8B%D0%B5_%D0%BB%D1%83%D1%87%D0%B8_%D1%81%D0%BE%D0%BB%D0%BD%D1%86%D0%B0.jpg) no-repeat;
background-size: cover;
position: relative;
height: 500px;
overflow: hidden;
z-index: 1;
}
#childCropper {
border: 2px dashed #ccc;
position: absolute;
top: 50px;
left: 50px;
height: 200px;
width: 200px;
}
#childCropper:after {
content: "";
width: 100%;
height: 100%;
border: 1000px solid rgba(0, 0, 0, 0.5);
position: absolute;
top: -1000px;
left: -1000px;
z-index: -1;
}
<div id="grandparentImage">
<div id="childCropper"></div>
</div>
Note: There will be no need for the #parentOverlay element anymore. Also this solution requires the grand-parent element to have an overflow: hidden property and a z-index (why?).
I'm guessing this is what you're looking for:
overlay-mask {
background-color: rgba(0,0,0,.65);
clip-path: polygon(0% 0%, 75% 0%, 75% 25%, 25% 25%, 25% 75%, 75% 75%, 75% 0%, 100% 0%, 100% 100%, 0 100%);
z-index: 1;
pointer-events: none;
/* rest is optional, you could use
* `position:absolute` to place it in a parent with `relative`
*/
position: fixed;
top: 0; bottom: 0; left: 0; right: 0;
}
body {
margin: 0;
background: url("https://loremflickr.com/800/600") no-repeat center center /cover;
min-height: 100vh;
}
<overlay-mask></overlay-mask>
It's a simple shape following the polygon of the dark area. Points position can be expressed in percentage, using calc() or even providing a custom <svg> by id (and use an external tool, like Adobe Illustrator to generate it.
Current browser coverage: 87.99%.
You can have any content under the mask. And, instead of using position:fixed, you could use position:absolute and place it in the desired container with position:relative, to apply to that container.
Another method is to use <svg>s <path>. Animating them is pretty straight forward using either smil animations or plain CSS keyframes.
Example:
#overlay-mask {
z-index: 1;
pointer-events: none;
/* rest is optional, you could use
* `position:absolute` to place it in a parent with `relative`
*/
position: fixed;
top: 0; bottom: 0; left: 0; right: 0;
color: rgba(0,0,0,.65);
width: calc(100% + 4px);
height: calc(100% + 4px);
left: -2px;
top: -2px;
}
body {
margin: 0;
background: url("https://loremflickr.com/800/600") no-repeat center center /cover;
min-height: 200vh;
}
h2 {color: white;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id="overlay-mask" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
preserveAspectRatio="none"
viewBox="0 0 600 600" width="600" height="600">
<defs>
<path d="M0 600L0 0L600 0L600 600L0 600ZM100 200L200 200L200 100L100 100L100 200Z" id="cutPath">
<animate attributeType="XML" attributeName="d"
values="M0 600L0 0L600 0L600 600L0 600ZM100 200L200 200L200 100L100 100L100 200Z; M0 600L0 0L600 0L600 600L0 600ZM200 300L300 300L300 200L200 200L200 200Z;M0 600L0 0L600 0L600 600L0 600ZM100 300L300 300L300 100L100 100L100 200Z;M0 600L0 0L600 0L600 600L0 600ZM100 200L200 200L200 100L100 100L100 100Z"
keyTimes="0; 0.33; 0.66; 1"
dur="3s" repeatCount="indefinite"
/>
</path>
</defs>
<use xlink:href="#cutPath" opacity="1" fill="currentColor" fill-opacity="1"></use>
<use xlink:href="#cutPath" opacity="1" fill="none" stroke="white" stroke-width="2"
stroke-dasharray="1,1"
></use>
</svg>
<h2>Scroll down...</h2>
Overlaying divs (Proof of Concept)
.parent,
.child {
background-image: url(https://scontent-lht6-1.cdninstagram.com/vp/0f18c710d8dc3ebd48819b3f9f44b5cc/5C28EE7E/t51.2885-15/e35/29094825_1798384780455300_8914767740305145856_n.jpg?se=7&ig_cache_key=MTc0MDQ5MzIwMjE5OTYyODM5MQ%3D%3D.2);
background-size: contain;
}
.parent {
height: 1072px;
width: 1072px;
opacity: 0.3
}
.child {
position: absolute;
top: 150px;
left: 20px;
height: 200px;
width:500px;
background-position: -20px -150px;
background-size: 1072px 1072px
}
<div class="parent"></div>
<div class="child"></div>
Here is another approach that uses only one element where you can rely on gradient and multiple background to create the cropped overlay and also the dotted border:
#grandparentImage {
--g:linear-gradient(rgba(0,0,0,0.5),rgba(0,0,0,0.5));
--t:repeating-linear-gradient(to right ,#ccc 0,#ccc 2px,transparent 2px, transparent 4px);
--b:repeating-linear-gradient(to bottom,#ccc 0,#ccc 2px,transparent 2px, transparent 4px);
background-image:
/*the border*/
var(--t),var(--t),var(--b),var(--b),
/*the overlay*/
var(--g),var(--g),var(--g),var(--g),
/*the image*/
url(https://picsum.photos/1000/800?image=1069);
background-size:
/*the border*/
40% 2px,40% 2px,2px 40%,2px 40%,
/*the overlay*/
100% 30%,100% 30%,20% 40%, 40% 40%,
/*the image*/
cover;
background-position:
/*the border*/
33.33% 30%,left 33.33% bottom 30%,20% 50%,60% 50%,
/*the overlay*/
top,bottom,left center,right center,
/*the image*/
center;
background-repeat:no-repeat;
position: relative;
height: 100vh;
}
body {
margin:0;
}
<div id="grandparentImage">
</div>
The overlay will be formed by 4 gradients as a rectangular shapes and each border will be a repeating gradient to alternate white/transparent.
The hard part is to understand the different values and how the caclulation of background-size/background-position is done. Here is a good reading for this: background-position not working in percentage for linear-gradient
We can also and the dots of your screenshot:
#grandparentImage {
--g:linear-gradient(rgba(0,0,0,0.5),rgba(0,0,0,0.5));
--t:repeating-linear-gradient(to right ,#ccc 0,#ccc 2px,transparent 2px, transparent 4px);
--b:repeating-linear-gradient(to bottom,#ccc 0,#ccc 2px,transparent 2px, transparent 4px);
--d:radial-gradient(#ccc 60%,transparent 62%);
background-image:
/*the dots*/
var(--d),var(--d),var(--d),var(--d),var(--d),var(--d),var(--d),var(--d),
/*the border*/
var(--t),var(--t),var(--b),var(--b),
/*the overlay*/
var(--g),var(--g),var(--g),var(--g),
/*the image*/
url(https://picsum.photos/1000/800?image=1069);
background-size:
/*the dots*/
10px 10px,10px 10px,10px 10px,10px 10px,10px 10px,10px 10px,10px 10px,10px 10px,
/*the border*/
40% 2px,40% 2px,2px 40%,2px 40%,
/*the overlay*/
100% 30%,100% 30%,20% 40%, 40% 40%,
/*the image*/
cover;
background-position:
/*the dots*/
20% 30%,20% 70%,20% 50%,60% 30%,60% 50%,60% 70%,40% 30%,40% 70%,
/*the border*/
33.33% 30%,left 33.33% bottom 30%,20% 50%,60% 50%,
/*the overlay*/
top,bottom,left center,right center,
/*the image*/
center;
background-repeat:no-repeat;
position: relative;
height: 100vh;
}
body {
margin:0;
}
<div id="grandparentImage">
</div>
i have 2 div like this
<div class="container">
<div class="one"></div>
<div class="two"></div>
</div>
CSS :
.container {
width:100%;
}
.one , .two {
width:50%;
display:inline-block;
}
I want to give this 2 divs a diagonal side color to be like this
I tried rotate but it gave me some white spot.
Can any one help me please ?
A single gradient on the parent will do the visual:
html {
min-height:100%;
background:linear-gradient(140deg, rgb(153, 180, 211)50%, rgb(217, 181, 150) 50%)
}
example on HTML background sized at 100% viewport's height at the minimum.
You can use clip paths and 2 div within a container,
https://codepen.io/anon/pen/OOXPmv
HTML
<div id="wrapper">
<div id="left"></div>
<div id="right"></div>
</div>
CSS
body, html {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
background: #ccc;
}
#wrapper {
width: 100%;
height: 100%;
background: #111;
}
#left {
position: absolute;
top: 0;
left: 0;
width: 101%; /* If you make it 100%, you get a bit of black showing along the diagonal */
height: 100%;
background: #99b4d3;
-webkit-clip-path: polygon(0 0, 76% 0, 24% 100%, 0% 100%);
clip-path: polygon(0 0, 76% 0, 24% 100%, 0% 100%);
}
#right {
position: absolute;
top: 0;
right: 0;
width: 100%;
height: 100%;
background: #d9b596;
-webkit-clip-path: polygon(76% 0, 100% 0, 100% 100%, 24% 100%);
clip-path: polygon(76% 0, 100% 0, 100% 100%, 24% 100%);
}
Try using an svg path css background property. See example below.
.container {
background: red;
height: 117px;
}
.one {
float: left;
width: 50%;
height: 117px;
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100%' height='100%' viewBox='0 0 100 100' fill='blue' preserveAspectRatio='none'><path d='M0 0 L0 100 L50 100 L100 0 Z' /></svg>") no-repeat;
}
.two {
float: left;
width: 50%;
height: 117px;
}
<div class="container">
<div class="one"></div>
<div class="two"></div>
</div>
I'm designing a little web page, just for practicing(I'm a begginer), and as the title says, I need to create a triangle with a background image.
I have this model that I created :
My website
I'm talking about the triangles on the up-right corner of the "posts"
The only way I know of creating a triagle is with borders in CSS, but that won't help because of the image I need to use.
Maybe you have other idea
Thanks !
Tell me if you need help getting this in to your own code, here's the example:
div {
position: absolute;
width: 128px;
height: 128px;
background-image: url(http://i.imgur.com/envk4PP.png);
background-repeat: no-repeat;
background-size: cover;
-webkit-clip-path: polygon(0 12%, 0 86%, 35% 50%);
clip-path: polygon(0 0%, 100% 100%, 100% 0%);
}
<div></div>
I have to do something similar for a website, this is my example. I hope you can use it.
.overheader{
padding: 40px 0;
-webkit-clip-path: polygon(0 0, 0% 0, 20.3% 100%, 0% 100%);
-moz-clip-path: polygon(0 0, 0% 0, 20.3% 100%, 0% 100%);
clip-path: polygon(0 0, 0% 0, 20.3% 100%, 0% 100%);
background-image: url('http://www.todofermentacion.cl/assets/img/cerveza.png');
}
.page-header {
padding: 50px;
}
<div class="page-header">
<div class="overheader">
</div>
</div>
You have to modify the parameters of polygon to make the triangle anyway you want
Another option:
.post {
/* not important */
margin: 100px;
width: 10rem;
height: 5rem;
border: solid 1px black;
background: ivory;
padding: 1rem;
/* important */
position: relative;
overflow: hidden;
}
.post:after {
position: absolute;
display: block;
content: " ";
background-image: url(https://www.gravatar.com/avatar/614f3577183f1a9219884f73ec2538fd);
transform: rotate(45deg);
width: 50px;
height: 50px;
/* move it half the width*/
top: -25px;
right: -25px;
}
<div class="post">
Here is my post
</div>
:root{
--imageblockwidth: 105px;
--imageblockheight: 80px;
/*css variables*/
}
.imagediv {
width: var(--imageblockwidth);
height: var(--imageblockheight);
background-image: url(https://i.ytimg.com/vi/2fb-g_V-UT4/hqdefault.jpg);
background-size: contain;
background-repeat: no-repeat;
}
.imageoverlapper {
width: var(--imageblockwidth);
height: var(--imageblockheight);
box-sizing: border-box;
/*triangles using borders*/
border-top: var(--imageblockheight) solid rgba(0,0,0,0);
border-left: var(--imageblockwidth) solid yellow;
position: relative;
top : calc(-1*var(--imageblockheight));
}
<div class="imagediv"></div>
<div class="imageoverlapper"></div>
Just overlap rectangle with background image by triangle
I am trying to create a shape like in the image below with a slanted edge on only one side (for example, the bottom side) while the other edges remain straight.
I tried using the border method (code is given below) but the dimensions of my shape are dynamic and hence I cannot use this method.
.shape {
position: relative;
height: 100px;
width: 200px;
background: tomato;
}
.shape:after {
position: absolute;
content: '';
height: 0px;
width: 0px;
left: 0px;
bottom: -100px;
border-width: 50px 100px;
border-style: solid;
border-color: tomato tomato transparent transparent;
}
<div class="shape">
Some content
</div>
I have also tried using gradients for background (like in the below code) but it gets messed up as the dimensions change. You can see what I mean by hovering on the shape in the below snippet.
.gradient {
display: inline-block;
vertical-align: top;
height: 200px;
width: 100px;
margin: 10px;
color: beige;
transition: all 1s;
padding: 10px;
background: linear-gradient(45deg, transparent 45%, tomato 45%) no-repeat;
}
.gradient:hover {
width: 200px;
}
<div class="gradient"></div>
How can I create this shape with a slanted side and also be able to support dynamic sizes?
There are many ways to create the shape with a slanted edge only on one side.
The following methods cannot support dynamic sizes as already mentioned in the question:
Border triangle method with pixel values for border-width.
Linear gradients with the angle syntax (like 45deg, 30deg etc).
The methods that can support dynamic sizes are described below.
Method 1 - SVG
(Browser Compatibility)
SVG can be used to produce the shape either by using polygons or paths. The below snippet makes use of polygon. Any text content required can be positioned on top of the shape.
$(document).ready(function() {
$('#increasew-vector').on('click', function() {
$('.vector').css({
'width': '150px',
'height': '100px'
});
});
$('#increaseh-vector').on('click', function() {
$('.vector').css({
'width': '100px',
'height': '150px'
});
});
$('#increaseb-vector').on('click', function() {
$('.vector').css({
'width': '150px',
'height': '150px'
});
});
})
div {
float: left;
height: 100px;
width: 100px;
margin: 20px;
color: beige;
transition: all 1s;
}
.vector {
position: relative;
}
svg {
position: absolute;
margin: 10px;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
z-index: 0;
}
polygon {
fill: tomato;
}
.vector > span {
position: absolute;
display: block;
padding: 10px;
z-index: 1;
}
.vector.top > span{
height: 50%;
width: 100%;
top: calc(40% + 5px); /* size of the angled area + buffer */
left: 5px;
}
.vector.bottom > span{
height: 50%;
width: 100%;
top: 5px;
left: 5px;
}
.vector.left > span{
width: 50%;
height: 100%;
left: 50%; /* size of the angled area */
top: 5px;
}
.vector.right > span{
width: 50%;
height: 100%;
left: 5px;
top: 5px;
}
/* Just for demo */
body {
background: radial-gradient(circle at 50% 50%, aliceblue, steelblue);
}
polygon:hover, span:hover + svg > polygon{
fill: steelblue;
}
.btn-container {
position: absolute;
top: 0px;
right: 0px;
width: 150px;
}
button {
width: 150px;
margin-bottom: 10px;
}
.vector.left{
clear: both;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="vector bottom">
<span>Some content</span>
<svg viewBox="0 0 40 100" preserveAspectRatio="none">
<polygon points="0,0 40,0 40,100 0,60" />
</svg>
</div>
<div class="vector top">
<span>Some content</span>
<svg viewBox="0 0 40 100" preserveAspectRatio="none">
<polygon points="0,40 40,0 40,100 0,100" />
</svg>
</div>
<div class="vector left">
<span>Some content</span>
<svg viewBox="0 0 40 100" preserveAspectRatio="none">
<polygon points="0,0 40,0 40,100 20,100" />
</svg>
</div>
<div class="vector right">
<span>Some content</span>
<svg viewBox="0 0 40 100" preserveAspectRatio="none">
<polygon points="0,0 20,0 40,100 0,100" />
</svg>
</div>
<div class='btn-container'>
<button id="increasew-vector">Increase Width</button>
<button id="increaseh-vector">Increase Height</button>
<button id="increaseb-vector">Increase Both</button>
</div>
Pros
SVG is designed to produce scalable graphics and can work well with all dimension changes.
Borders and hover effect can be achieved with minimal coding overhead.
Image or gradient background can also be provided to the shape.
Cons
Browser support is probably the only downside because IE8- doesn't support SVG but that can be mitigated by using libraries like Raphael and also VML. Moreover, the browser support is in no way worse than the other options.
Method 2 - Gradient Background
(Browser Compatibility)
Linear gradients can still be used to produce the shape but not with angles as mentioned in the question. We have to use the to [side] [side] syntax (thanks to vals) instead of specifying angles. When sides are specified, the gradient angles are automatically adjusted based on the container's dimensions.
$(document).ready(function() {
$('#increasew-gradient').on('click', function() {
$('.gradient').css({
'height': '100px',
'width': '150px'
});
});
$('#increaseh-gradient').on('click', function() {
$('.gradient').css({
'height': '150px',
'width': '100px'
});
});
$('#increaseb-gradient').on('click', function() {
$('.gradient').css({
'height': '150px',
'width': '150px'
});
});
})
div {
float: left;
height: 100px;
width: 100px;
margin: 10px 20px;
color: beige;
transition: all 1s;
}
.gradient{
position: relative;
}
.gradient.bottom {
background: linear-gradient(to top right, transparent 50%, tomato 50%) no-repeat, linear-gradient(to top right, transparent 0.1%, tomato 0.1%) no-repeat;
background-size: 100% 40%, 100% 60%;
background-position: 0% 100%, 0% 0%;
}
.gradient.top {
background: linear-gradient(to bottom right, transparent 50%, tomato 50%) no-repeat, linear-gradient(to bottom right, transparent 0.1%, tomato 0.1%) no-repeat;
background-size: 100% 40%, 100% 60%;
background-position: 0% 0%, 0% 100%;
}
.gradient.left {
background: linear-gradient(to top right, transparent 50%, tomato 50%) no-repeat, linear-gradient(to top right, transparent 0.1%, tomato 0.1%) no-repeat;
background-size: 40% 100%, 60% 100%;
background-position: 0% 0%, 100% 0%;
}
.gradient.right {
background: linear-gradient(to top left, transparent 50%, tomato 50%) no-repeat, linear-gradient(to top left, transparent 0.1%, tomato 0.1%) no-repeat;
background-size: 40% 100%, 60% 100%;
background-position: 100% 0%, 0% 0%;
}
.gradient span{
position: absolute;
}
.gradient.top span{
top: calc(40% + 5px); /* background size + buffer */
left: 5px;
height: 50%;
}
.gradient.bottom span{
top: 5px;
left: 5px;
height: 50%;
}
.gradient.left span{
left: 40%; /* background size */
top: 5px;
width: 50%;
}
.gradient.right span{
left: 5px;
top: 5px;
width: 50%;
}
/* Just for demo */
body {
background: radial-gradient(circle at 50% 50%, aliceblue, steelblue);
}
.btn-container {
position: absolute;
top: 0px;
right: 0px;
width: 150px;
}
button {
width: 150px;
margin-bottom: 10px;
}
.gradient.left{
clear:both;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="gradient bottom"><span>Some content</span>
</div>
<div class="gradient top"><span>Some content</span>
</div>
<div class="gradient left"><span>Some content</span>
</div>
<div class="gradient right"><span>Some content</span>
</div>
<div class='btn-container'>
<button id="increasew-gradient">Increase Width</button>
<button id="increaseh-gradient">Increase Height</button>
<button id="increaseb-gradient">Increase Both</button>
</div>
Pros
Shape can be achieved and maintained even if the dimensions of the container are dynamic.
Hover effect can be added by changing the gradient color.
Cons
Hover effect will be triggered even when cursor is outside the shape but within the container.
Adding borders would require tricky gradient manipulations.
Gradients are known for producing jagged corners when the width (or height) is very big.
Image backgrounds cannot be used on the shape.
Method 3 - Skew Transforms
(Browser Compatibility)
In this method, a pseudo-element is added, skewed and positioned in such a way that it looks like one of the edges is slanted/angled.If the top or bottom edge is slanted, the skew should be along Y axis, else the rotation should be along X axis. The transform-origin should have the side opposite to the slanted side.
$(document).ready(function() {
$('#increasew-skew').on('click', function() {
$('.skew').css({
'height': '100px',
'width': '150px'
});
});
$('#increaseh-skew').on('click', function() {
$('.skew').css({
'height': '150px',
'width': '100px'
});
});
$('#increaseb-skew').on('click', function() {
$('.skew').css({
'height': '150px',
'width': '150px'
});
});
})
div {
float: left;
height: 100px;
width: 100px;
margin: 50px;
color: beige;
transition: all 1s;
}
.skew {
padding: 10px;
position: relative;
background: tomato;
}
.skew:after {
position: absolute;
content: '';
background: inherit;
z-index: -1;
}
.skew.bottom:after,
.skew.top:after {
width: 100%;
height: 60%;
}
.skew.left:after,
.skew.right:after {
height: 100%;
width: 60%;
}
.skew.bottom:after {
bottom: 0px;
left: 0px;
transform-origin: top left;
transform: skewY(22deg);
}
.skew.top:after {
top: 0px;
left: 0px;
transform-origin: top left;
transform: skewY(-22deg);
}
.skew.left:after {
top: 0px;
left: 0px;
transform-origin: bottom left;
transform: skewX(22deg);
}
.skew.right:after {
top: 0px;
right: 0px;
transform-origin: bottom right;
transform: skewX(-22deg);
}
.skew:hover {
background: steelblue;
}
/* Just for demo */
body {
background: radial-gradient(circle at 50% 50%, aliceblue, steelblue);
}
.skew.bottom {
margin-top: 10px;
}
.skew.left {
clear: both;
}
.btn-container {
position: absolute;
top: 0px;
right: 0px;
width: 150px;
}
button {
width: 150px;
margin-bottom: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="skew bottom">Some content</div>
<div class="skew top">Some content</div>
<div class="skew left">Some content</div>
<div class="skew right">Some content</div>
<div class='btn-container'>
<button id="increasew-skew">Increase Width</button>
<button id="increaseh-skew">Increase Height</button>
<button id="increaseb-skew">Increase Both</button>
</div>
Pros
Shape can be achieved even with borders.
Hover effect will be restricted to within the shape.
Cons
Dimensions need to increase proportionally for the shape to be maintained because when an element is skewed, its offset in Y-axis increases as width increases and vice-versa (try increasing the width to 200px in the snippet). You can find more information about this here.
Method 4 - Perspective Transforms
(Browser Compatibility)
In this method, the main container is rotated along the X or Y axis with a bit of perspective. Setting the appropriate value to transform-origin would produce a slanted edge on only one side.
If the top or bottom side is slanted, the rotation should be along Y axis, else the rotation should be along X axis. The transform-origin should have the side opposite to the slanted side.
$(document).ready(function() {
$('#increasew-rotate').on('click', function() {
$('.rotate').css({
'height': '100px',
'width': '150px'
});
});
$('#increaseh-rotate').on('click', function() {
$('.rotate').css({
'height': '150px',
'width': '100px'
});
});
$('#increaseb-rotate').on('click', function() {
$('.rotate').css({
'height': '150px',
'width': '150px'
});
});
})
div {
float: left;
height: 100px;
width: 100px;
margin: 50px;
color: beige;
transition: all 1s;
}
.rotate {
position: relative;
width: 100px;
background: tomato;
}
.rotate.bottom {
transform-origin: top;
transform: perspective(10px) rotateY(-2deg);
}
.rotate.top {
transform-origin: bottom;
transform: perspective(10px) rotateY(-2deg);
}
.rotate.left {
transform-origin: right;
transform: perspective(10px) rotateX(-2deg);
}
.rotate.right {
transform-origin: left;
transform: perspective(10px) rotateX(-2deg);
}
.rotate span {
position: absolute;
display: block;
top: 0px;
right: 0px;
width: 50%;
height: 100%;
}
.rotate.bottom span {
padding: 10px;
transform-origin: top;
transform: perspective(10px) rotateY(2deg);
}
.rotate.top span {
padding: 20px;
transform-origin: bottom;
transform: perspective(20px) rotateY(2deg);
}
.rotate.left span {
padding: 10px;
transform-origin: right;
transform: perspective(10px) rotateX(2deg);
}
.rotate.right span {
padding: 0px 30px;
transform-origin: left;
transform: perspective(10px) rotateX(2deg);
}
.rotate:hover {
background: steelblue;
}
/* Just for demo */
body {
background: radial-gradient(circle at 50% 50%, aliceblue, steelblue);
}
.rotate.left{
clear:both;
}
.btn-container {
position: absolute;
top: 0px;
right: 0px;
width: 150px;
}
button {
width: 150px;
margin-bottom: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="rotate bottom"><span>Some content</span>
</div>
<div class="rotate top"><span>Some content</span>
</div>
<div class="rotate left"><span>Some content</span>
</div>
<div class="rotate right"><span>Some content</span>
</div>
<div class='btn-container'>
<button id="increasew-rotate">Increase Width</button>
<button id="increaseh-rotate">Increase Height</button>
<button id="increaseb-rotate">Increase Both</button>
</div>
Pros
Shape can be achieved with borders.
Dimensions need not increase proportionally for the shape to be maintained.
Cons
Content will also be rotated and hence they have to be counter rotated to look normal.
Positioning text will be tedious if the dimensions are not static.
Method 5 - CSS Clip Path
(Browser Compatibility)
In this method, the main container is clipped into the required shape using a polygon. The polygon's points should be modified depending on the side where the slanted edge is required.
$(document).ready(function() {
$('#increasew-clip').on('click', function() {
$('.clip-path').css({
'height': '100px',
'width': '150px'
});
});
$('#increaseh-clip').on('click', function() {
$('.clip-path').css({
'height': '150px',
'width': '100px'
});
});
$('#increaseb-clip').on('click', function() {
$('.clip-path').css({
'height': '150px',
'width': '150px'
});
});
})
.clip-path {
position: relative;
float: left;
margin: 20px;
height: 100px;
width: 100px;
background: tomato;
padding: 4px;
transition: all 1s;
}
.clip-path.bottom {
-webkit-clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 60%);
}
.clip-path.top {
-webkit-clip-path: polygon(0% 40%, 100% 0%, 100% 100%, 0% 100%);
}
.clip-path.left {
-webkit-clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 40% 100%);
}
.clip-path.right {
-webkit-clip-path: polygon(0% 0%, 60% 0%, 100% 100%, 0% 100%);
}
.clip-path .content {
position: absolute;
content: '';
height: calc(100% - 10px);
width: calc(100% - 8px);
background: bisque;
}
.clip-path.bottom .content {
-webkit-clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 60%);
}
.clip-path.top .content {
-webkit-clip-path: polygon(0% 40%, 100% 0%, 100% 100%, 0% 100%);
}
.clip-path .content.img {
top: 6px;
background: url(http://lorempixel.com/250/250);
background-size: 100% 100%;
}
/* Just for demo */
body {
background: radial-gradient(circle at 50% 50%, aliceblue, steelblue);
}
.clip-path.left {
clear: both;
}
.clip-path:hover {
background: gold;
}
.btn-container {
position: absolute;
top: 0px;
right: 0px;
margin: 20px;
width: 150px;
}
button {
width: 150px;
margin-bottom: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="clip-path bottom">
<div class="content">abcd</div>
</div>
<div class="clip-path top">
<div class="content img"></div>
</div>
<div class="clip-path left"></div>
<div class="clip-path right"></div>
<div class='btn-container'>
<button id="increasew-clip">Increase Width</button>
<button id="increaseh-clip">Increase Height</button>
<button id="increaseb-clip">Increase Both</button>
</div>
Pros
Shape can be maintained even when the container is being resized dynamically.
Hover effect will be perfectly restricted within the borders of the shape.
Image can also be used as background for the shape.
Cons
Browser support is very poor at present.
Borders can be added by placing an absolutely positioned element on top of the shape and giving it the necessary clip but beyond a point it doesn't fit well when re-sizing dynamically.
Method 6 - Canvas
(Browser Compatibility)
Canvas can also be used to produce the shape by drawing paths. The below snippet has a demo. Any text content required can be positioned on top of the shape.
window.onload = function() {
var canvasEls = document.getElementsByTagName('canvas');
for (var i = 0; i < canvasEls.length; i++) {
paint(canvasEls[i]);
}
function paint(canvas) {
var ctx = canvas.getContext('2d');
ctx.beginPath();
if (canvas.className == 'bottom') {
ctx.moveTo(0, 0);
ctx.lineTo(250, 0);
ctx.lineTo(250, 100);
ctx.lineTo(0, 60);
} else if (canvas.className == 'top') {
ctx.moveTo(0, 40);
ctx.lineTo(250, 0);
ctx.lineTo(250, 100);
ctx.lineTo(0, 100);
} else if (canvas.className == 'left') {
ctx.moveTo(0, 0);
ctx.lineTo(250, 0);
ctx.lineTo(250, 100);
ctx.lineTo(60, 100);
} else if (canvas.className == 'right') {
ctx.moveTo(0, 0);
ctx.lineTo(190, 0);
ctx.lineTo(250, 100);
ctx.lineTo(0, 100);
}
ctx.closePath();
ctx.lineCap = 'round';
ctx.fillStyle = 'tomato';
ctx.fill();
}
$('#increasew-canvas').on('click', function() {
$('.container').css({
'width': '150px',
'height': '100px'
});
});
$('#increaseh-canvas').on('click', function() {
$('.container').css({
'width': '100px',
'height': '150px'
});
});
$('#increaseb-canvas').on('click', function() {
$('.container').css({
'width': '150px',
'height': '150px'
});
});
};
.container {
float: left;
position: relative;
height: 100px;
width: 100px;
margin: 20px;
color: beige;
transition: all 1s;
}
canvas {
height: 100%;
width: 100%;
}
.container > span {
position: absolute;
top: 5px;
left: 5px;
padding: 5px;
}
.top + span {
top: 40%; /* size of the angled area */
}
.left + span {
left: 40%; /* size of the angled area */
}
/* Just for demo */
body {
background: radial-gradient(circle at 50% 50%, aliceblue, steelblue);
}
.btn-container {
position: absolute;
top: 0px;
right: 0px;
width: 150px;
}
button {
width: 150px;
margin-bottom: 10px;
}
div:nth-of-type(3) {
clear: both;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="container">
<canvas height="100px" width="250px" class="bottom"></canvas> <span>Some content</span>
</div>
<div class="container">
<canvas height="100px" width="250px" class="top"></canvas> <span>Some content</span>
</div>
<div class="container">
<canvas height="100px" width="250px" class="left"></canvas> <span>Some content</span>
</div>
<div class="container">
<canvas height="100px" width="250px" class="right"></canvas> <span>Some content</span>
</div>
<div class='btn-container'>
<button id="increasew-canvas">Increase Width</button>
<button id="increaseh-canvas">Increase Height</button>
<button id="increaseb-canvas">Increase Both</button>
</div>
Pros
Shape can be achieved and maintained even if the dimensions of the container are dynamic. Borders can also be added.
Hover effect can be restricted to within the shape's boundaries by using pointInpath method.
Image or gradient background can also be provided to the shape.
Better choice if real-time animation effects are needed as it doesn't require DOM manipulation.
Cons
Canvas is raster based and hence the angled edges will become pixelated or blurred when scaled beyond a point *.
* - Avoiding pixelation would need repaints of the shape whenever viewport is resized. There is an example of it here but that is an overhead.
I tried using the border method but the dimensions of my shape are dynamic and hence I cannot use this method.
Method 7 - Viewport Units (Border Redux)
(Browser Compatibility)
Viewport Units are a great innovation in CSS3. While you can usually use percentage values to dynamize your properties, you can't do it for border-widths (nor for font-sizes).
With Viewport Units instead you can dynamically set your border widths, along with the sizes of your objects, compared to the viewport dimension.
Note: percentage values are referred to the parent object, not to the viewport (visible area of the window).
To test the method, launch the following snippet Full Page and resize it both horizontally and vertically.
.shape {
position: relative;
height: 20vh;
width: 40vw;
background: tomato;
}
.shape:after {
position: absolute;
content: '';
left: 0px;
right: 0px;
top: 20vh;
border-width: 10vh 20vw;
border-style: solid;
border-color: tomato tomato rgba(0,0,0,0) rgba(0,0,0,0);
}
<div class="shape">Some content</div>
Pros - (1) Everything is dynamic, browser coverage is wide.
Cons - (1) You should pay attention at how your OS handles the scrollbar with overflow: auto;.
My solution is inspired by the one called Method 7 - Viewport Units by Andrea Ligios, above in this page.
I used the "horizontal" unit for the height too (height:10vw) to keep the given proportions in the trapezoid when resizing the width of the navigation window. We could call this Method 7b - Viewport Width.
Further, using two nested divs, instead of one and the :after selector, allows a better tuning of the text content styles, in my opinion (e.g. text-align, etc.).
.dtrapz {
position: relative;
margin: 10px 40vw;
width: 0;
height: 10vw;
border: none;
border-right: 20vw solid #f22;
border-bottom: 5vw solid transparent;
}
.dtcont {
position: absolute;
width: 20vw;
height: 10vw;
text-align: center;
color: #fff;/* just aesthetic */
}
<div class="dtrapz">
<div class="dtcont">Some content</div>
</div>