Sometimes images just explain things better than 1000 words
assumed the black border is my image I want to cut off the top left/right edge - like marked by the red lines.
Would it be possible (if yes: how) to cut an image this way with CSS?
Just in case its not clear what I mean by cut: I want
By cut I mean, that the image will look like this
Without using a wrapper element, you can use clip-path, though the support isn't great.
img.cut {
-webkit-clip-path: polygon(50px 0, calc(100% - 50px) 0, 100% 50px, 100% 100%, 0 100%, 0 50px);
clip-path: polygon(50px 0, calc(100% - 50px) 0, 100% 50px, 100% 100%, 0 100%, 0 50px);
}
<img class="cut" src="http://lorempixel.com/200/300/">
This uses calc (widely supported), so you can specify exact pixel values to clip by.
CSS Pseudo
If you know you're background is going to remain a solid colour, you can achieve this using pseudo elements in a number of ways.
1st option
A very simple solution is to use the pseudo elements with borders to which should get you the effect you want.
div {
height: 300px;
background: red;
position: relative;
}
div:before {
content: '';
position: absolute;
top: 0;
left: 0;
border-top: 80px solid white;
border-right: 80px solid red;
width: 0;
}
div:after {
content: '';
position: absolute;
top: 0;
right: 0;
border-top: 80px solid white;
border-left: 80px solid red;
width: 0;
}
<div></div>
2nd Option
Using a single pseudo element which is larger than the parent and rotating it to get the desired effect.
This is a much cleaner effect and also means the use of background images is supported and easier to implement.
div {
height: 200px;
width: 200px;
background: transparent;
position: relative;
z-index: 9;
overflow: hidden;
}
div:before {
content: '';
width: 200%;
height: 200%;
position: absolute;
transform: rotate(45deg);
background: red;
left: -50%;
top: 20px;
<div></div>
Related
I'm using the box shadow property to replicate the original circle multiple times, with different spread each shadow, see:
.a {
width: 50px;
height: 50px;
background: #EEB850;
border-radius: 50%;
position: relative;
top: 117;
left: 167;
box-shadow: 0 0 0 50px #243D83,
0 0 0 100px #6592CF;
}
However, the shadows are not replicating the circle, but instead, they look like squares with rounded corners. Any suggestion about this? Screenshot of the result.
While there is the bug in Edge/Chrome a workaround might be to create the circles with radial-gradients on a larger before pseudo element.
Here's a simple example:
.a {
width: 50px;
height: 50px;
background: #EEB850;
border-radius: 50%;
position: relative;
top: 117px;
left: 167px;
}
.a::before {
content: '';
position: absolute;
display: inline-block;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 400%;
height: 400%;
border-radius: 50%;
background-image: radial-gradient(#EEB850 0 25px, #243D83 25px 50px, #6592CF 50px 75px, transparent 75px 100%);
background-position: top left;
}
<div class="a"></div>
Note: because one can sometimes get ragged effects with radial gradient the snippet has put the central color as its first circle to avoid edge effects (small gaps between the element and the radial gradient).
I've tried the perspective solution here How to transform each side of a shape separately? but can't get it to work probably due to the irregularness of the shape. Only the top and right side columns are slanted, vertical and bottom are straight. How can I do this with CSS?
Using CSS borders you can create triangles and trapezoids.
You can achieve your shape joining a triangle and a trapezoid.
.triangle {
border: 0 solid red;
border-left-width: 500px;
border-top-width: 30px;
border-top-color: transparent;
}
.trapezoid {
border: 0 solid red;
width: 500px;
border-bottom-width: 150px;
border-right-width: 30px;
border-right-color: transparent;
}
<div class="triangle"></div>
<div class="trapezoid"></div>
Method 1: Clip path
You could make use of CSS clip-path feature to clip a rectangle into the required polygon shape.
div {
box-sizing: border-box;
height: 150px;
width: 250px;
background: red;
padding: 10px;
-webkit-clip-path: polygon(0% 0%, 90% 10%, 100% 100%, 0% 100%);
clip-path: polygon(0% 0%, 90% 10%, 100% 100%, 0% 100%);
}
div#image {
background: url(http://lorempixel.com/400/200);
}
/* Just for demo */
div{
float: left;
margin: 10px;
transition: all 1s;
}
div:hover{
height: 200px;
width: 300px;
}
<div>Some text</div>
<div id="image"></div>
Pros:
Supports non-solid color fills inside the shape and also allow text to be present inside.
The shape is responsive and can adapt even if the container's dimensions change.
Cons:
Poor browser support for the CSS clip-path feature. This can be overcome by using inline SVG for the clip-path like in the below snippet as this has much better browser support.
div {
box-sizing: border-box;
height: 150px;
width: 250px;
padding: 10px;
background: red;
-webkit-clip-path: url(#clip);
clip-path: url(#clip);
}
div#image {
background: url(http://lorempixel.com/400/200);
}
/* Just for demo */
div{
float: left;
margin: 10px;
transition: all 1s;
}
div:hover{
height: 200px;
width: 300px;
}
<svg width="0" height="0">
<defs>
<clipPath id="clip" clipPathUnits="objectBoundingBox">
<path d="M0 0, 0.9 0.1, 1 1, 0 1z" />
</clipPath>
</defs>
</svg>
<div>
Some text
</div>
<div id="image"></div>
Method 2: CSS Transforms
Generally it is better not to use transforms when there is going to be content like image or text inside the shape (or) when the shape's background is not going to be a solid color because then we would either have to (a) reverse transform the child elements separately to make them look normal or (b) use absolute positioning.
For this particular shape, having text inside the shape is not a problem even while using transforms but having non solid background colors would be.
Option 1: Using two pseudo-elements
You could use a couple of pseudo-elements with skew transforms, position one on the top and the other on the right to produce the required shape. Hover the shape in snippet to see how it is created.
div {
position: relative;
height: 150px;
width: 250px;
background: red;
margin: 40px 40px 0px 0px;
}
div:after,
div:before {
position: absolute;
content: '';
background: red;
z-index: -1;
backface-visibility: hidden;
}
div:before {
height: 12.5%;
width: 100%;
top: 0px;
left: 0px;
transform-origin: right top;
transform: skewY(3deg);
}
div:after {
height: 100%;
width: 12.5%;
right: -1px;
top: -1px;
transform-origin: right top;
transform: skewX(10deg);
}
/* Just for demo */
div{
transition: all 1s;
}
div:hover{
height: 250px;
width: 300px;
}
div:hover:after{
background: blue;
}
div:hover:before{
background: green;
}
<div>Some text</div>
Pros:
Shape can be created with a single element and can have text inside it without any trouble.
Cons:
Having gradients (or) images as background for the shape is complex because they would need reverse rotation as mentioned earlier.
Shape is not 100% scalable as dimensions of the container should change proportionately for the shape to be maintained (hover on the shape in the snippet to see what I mean). Reason is same as mentioned here.
Option 2: Using one pseudo-element
This is pretty similar to the previous option except that this uses a single pseudo-element along with a overflow: hidden on the parent.
div {
position: relative;
box-sizing: border-box;
height: 200px;
width: 300px;
padding: 10px;
overflow: hidden;
}
div:after {
position: absolute;
content: '';
top: 0px;
left: -20px;
height: 100%;
width: 100%;
background: red;
transform-origin: left bottom;
transform: skewY(5deg) skewX(7.5deg);
z-index: -1;
}
div:hover {
height: 300px;
width: 500px;
transition: all 1s;
}
<div>Some text</div>
Pros:
Shape can be created with a single element and can have text inside it without any trouble.
Shape is responsive and can adapt even if the container's dimensions change .
Cons:
Same constraint as the previous option for gradient and image backgrounds.
Not suitable if the overflow: hidden on the parent is a constraint.
A solution is:
div {
width: 300px;
height: 100px;
margin:50px;
background-color: yellow;
border: 1px solid black;
}
.thisdiv {
-ms-transform: skewX(-20deg); /* IE 9 */
-webkit-transform: skewX(-20deg); /* Safari */
transform: skewX(-20deg); /* Standard syntax */
}
<div class="thisdiv">
This is the div I will skew
</div>
This is how to skew an element, if you want to make the shape you added, try using two overlaping div's, position, scale, rotate and skew, like this:
.outer-div{
position:relative;
margin:50px;
width:200px;
height:200px;
border:2px black dashed;
}
.inner-one{
position:absolute;
left:0;
bottom:0;
width:180px;
height:180px;
background:red;
}
.inner-two{
position:absolute;
bottom:2px;
right:0px;
width:200px;
height:195px;
background:red;
transform: rotate(7deg) skew(14deg) scale(0.905); /* Standard syntax */
}
<div class="outer-div">
<div class="inner-one">
</div>
<div class="inner-two">
</div>
</div>
2 Triangle Solution for Irregular Quadrilateral in CSS
In looking at your image, I notice that the skew at the top and right are really just long, narrow triangles overlaying the rectangle.
So what I did was create triangles using CSS border properties and absolutely position them over the rectangle.
#rectangle {
width: 400px;
height: 200px;
background-color: red;
margin-top: 25px;
position: relative;
}
#triangle-down {
border-left: 30px solid red;
border-right: 0;
border-top: 200px solid transparent;
position: absolute;
right: -30px;
top: 0;
}
#triangle-left {
border-top: 0;
border-bottom: 15px solid red;
border-right: 400px solid transparent;
position: absolute;
right: 0;
top: -15px;
}
<div id="rectangle">
<div id="triangle-down"></div>
<div id="triangle-left"></div>
</div>
jsFiddle demo
You could check out the clip-path property (see below from MDN), but support is very patchy. Chrome 24+ supports with prefix and FF, but only URL values, which reference a path in an SVG. You can read more about clip-path here.
Here's a basic pen - this will only work in Chrome.
From MDN
The clip-path CSS property prevents a portion of an element from getting displayed by defining a clipping region to be displayed i.e, only a specific region of the element is displayed. The clipping region is a path specified as a URL referencing an inline or external SVG, or shape method such as circle(). The clip-path property replaces the now deprecated clip property.
developer.mozilla.org/en-US/docs/Web/CSS/clip-path (sorry, not enough rep to link)
I'm not sure what is specific name for this shape but can I just called it "half Parallelogram" ? I want make this shape purely using CSS/CSS3. Any help? or tutorial?
You can do it using pseudo-elements like below. The approach is to cut out a triangle shape from the left-bottom and top-right of the box. This method can be used with either a solid color an image inside the shape as long as the body background is a solid color. When the body background is a non-solid color this approach will not work because the border hack needs a solid color background.
The advantage of this method is that it can support cuts of different angles at each side (like in the question where the hypotenuse of the triangular cut on either side are not parallel to each other).
div {
background: red;
width: 200px;
height: 100px;
position: relative;
}
div:before {
position: absolute;
height: 0;
width: 0;
content: ' ';
border: 20px solid white;
border-color: transparent transparent white white;
border-width: 20px 0px 0px 15px;
left: 0;
top: 80px;
}
div:after {
position: absolute;
height: 0;
width: 0;
content: ' ';
border: 20px solid white;
border-color: white white transparent transparent;
left: 170px;
top: 0px;
}
.with-img {
background: url(http://lorempixel.com/100/100);
}
<div></div>
<br>
<div class="with-img"></div>
Sample 2: You can also achieve a similar effect using gradients. Just 1 gradient is enough to produce a cut of similar angle on both sides. If different angles are required then two gradients should be used. However the multiple gradient approach mentioned here will not work when the body background is a non-solid color.
div {
width: 200px;
height: 100px;
position: relative;
}
.with-single-gradient {
background: linear-gradient(45deg, transparent 5%, yellowgreen 5%, yellowgreen 90%, transparent 90.5%);
}
.with-single-gradient.image {
background: linear-gradient(45deg, white 5%, transparent 5%, transparent 90%, white 90.5%), url(http://lorempixel.com/100/100);
}
.with-multiple-gradient.image {
background: linear-gradient(45deg, transparent 0%, transparent 90%, white 90%), linear-gradient(60deg, white 10%, transparent 5%, transparent 100%), url(http://lorempixel.com/100/100);
}
<div class='with-single-gradient'></div>
<br>
<div class='with-single-gradient image'></div>
<br>
<div class='with-multiple-gradient image'></div>
Sample 3: This can also be created using SVG and is the best method yet. All that it requires is just a single path element which creates the required shape.
<svg viewBox='0 0 100 60' width='200px' height='120px'>
<path d='M0,0 80,0 100,16 100,60 10,60 0,54z' fill='yellowgreen' />
</svg>
Tested on Chrome v24, Firefox v19, Safari v5.1.7 (on Windows) and IE v10. They are older versions but should work in the latest versions also.
Note: IE versions less than 10 do not support gradients as mentioned in this SO thread.
there's no thing as straight radius, but here you have some tutorials. For weird shapes, you need to use a combination of shape and negative space, basically using figures with the same color of the background . The good news is you could use "transparent" as color, so you can "fake" this figures in an easy way. See tutorials Shapes of CSS or yuo can use a generator like CSS Shape Generator or CSS Shape Generator 2 but they will highly depend on your needs. Personally, I'd use a BG image and be a happy camper
to make this shape you have to use pseudo class.
and i hope it will help you
div { display: inline-block; margin: 20px; float: left; }
shape {
width: 208px;
height: 130px;
background: red;
position: relative; }
shape:before {
content: "";
position: absolute;
top: 0;
left: 0;
border-bottom: 29px solid red;
border-right: 29px solid #fff;
width: 179px;
height: 0; }
shape:after {
content: "";
position: absolute;
bottom: 0;
left: 0;
border-top: 29px solid red;
border-left: 29px solid #fff;
width: 42px;
height: 0; }
demo
2 gradients and background-size can be used too :
div {
width: 1440px;
height: 590px;
background:
linear-gradient(45deg, transparent 80px, #FF0000 80px) left no-repeat,
linear-gradient(-135deg, transparent 160px, #FF0000 160px) top right no-repeat;
background-size: 50% 100%;
}
<div>
</div>
1 gradients and calc() can be used too :
div {
width: 1440px;
height: 590px;
background:
linear-gradient(45deg, transparent 80px, #FF0000 80px, #FF0000 calc( 100% - 160px), transparent calc( 100% - 160px) );
}
<div>
</div>
Related to duplicate question https://stackoverflow.com/questions/36932294/how-can-i-create-the-object-in-picture-below-using-css-border-radius :
div {
width:980px;
height:460px;
background:linear-gradient(140deg,transparent 200px, #FFCB05 200px) left no-repeat,
linear-gradient(-40deg,transparent 80px, #FFCB05 80px) top right no-repeat;
background-size:50% 100% ;
}
<div>
div shape
</div>
image
<img src="http://i.stack.imgur.com/M48zP.png" />
For the second shape use this:
border-bottom-left-radius:50px;
border-top-right-radius:50px;
Check JSFiddle Demo
Edit:
Question is edited and second shape has been removed.
You can add an element with overflow: hidden;
skew transform the parent by desired angle. Unskew the pseudoelement by the negative of that angle.
Using this approach, you can also add images to background.
div {
height: 100px;
width: 220px;
overflow: hidden;
position: relative;
-webkit-transform: skewX(45deg);
-moz-transform: skewX(45deg);
transform: skewX(45deg);
}
div:before {
content: '';
position: absolute;
left: 10px;
height: 100px;
width: 200px;
background: red;
-webkit-transform: skewX(-45deg);
-moz-transform: skewX(-45deg);
transform: skewX(-45deg);
}
<div></div>
FIDDLE
FIDDLE (with image)
Through help on stackoverflow I've been able to generate and position a CSS triangle in the correct position on my website, I've also learnt how to color a triangle in 2 equal halves.
But I am stuck on merging the two examples together, what I've tried I don't think is worth pasting here due to the mess I've made of it.
I am trying to get a triangle that has the proportions and sits at the bottom of the div like this fiddle example and then is split in 2 colors like this fiddle example.
Where I believe I am going wrong is that in the different fiddles there are different uses of:
:before
Well..., Here is my attempt to achieve this effect (proportions + split in 2 colors):
JSFiddle Demo.
In this demo, I added the triangle to the .bottom div and positioned that to stay at the top (with a negative value).
Then added margin-top: 1%; property to move the triangle when resizing the window:
HTML
<div class="top"></div>
<div class="bottom">
<div class="triangle"></div>
</div>
CSS:
.top {
/* other styles... */
position: relative;
z-index: 2;
}
.bottom {
background: lightGreen;
height: 100px;
position: relative;
z-index: 1; /* A lower z-index value than .top */
/* Or use overflow: hidden; instead */
}
.triangle {
width: 40px;
height: 20px;
position: absolute;
left: 0;
right: 0;
top: -20px;
margin: auto;
margin-top: 1%; /* Move the triangle when resizing the window */
z-index: 1;
}
.triangle:before {
content: " ";
position: absolute;
width: 0;
height: 0;
border-style: solid;
border-width: 0 20px 20px 0;
border-color: transparent blue transparent transparent;
}
.triangle:after {
content: " ";
position: absolute;
left: 20px;
width: 0;
height: 0;
border-style: solid;
border-width: 20px 20px 0 0;
border-color: red transparent transparent transparent;
}
I'm trying to make a container that has an upward arrow attached to it. I am familiar with the border drawing trick and think that's a likely solution, but it only works for known sizes I think, since you have to specify border in em or px.
The shape I would like to make is this:
.
/ \
/ \
/ \
| flex |
| |
Where the content area can flex to different sizes as a percentage of a parent container.
Here is the CSS, with the problem area flagged:
.metric {
display: inline-block;
position: relative;
height: 150px;
width: 50%;
background: lawngreen;
}
.metric:after {
position: absolute;
top: -25px;
left: 0;
content: '';
background: white;
width: 100%;
height: 0;
border: 75px solid white; /* this fixed width is the problem */
border-top: none;
border-bottom: 25px solid lawngreen;
box-sizing: border-box;
}
Here is the jsfiddle: http://jsfiddle.net/C8XJW/2/
Do you guys know any way to pull this off?
Here is another posibility.
This one does the trick with gradient backgrounds. You need 2 of them, so that the diagonal is easily achieved:
Relevant CSS:
.metric:before, .metric:after {
position: absolute;
top: -25px;
content: '';
width: 50%;
height: 25px;
}
.metric:before {
left: 0px;
background: linear-gradient(to right bottom, transparent 50%, lawngreen 50%);
}
.metric:after {
right: 0px;
background: linear-gradient(to left bottom, transparent 50%, lawngreen 50%);
}
Updated Fiddle
The differences with Simple As Could Be solution:
Pro Transparent corners (relevant if you have a background)
Con Worse browser support
Here's one great solution. Bascially, you make the arrow always centered, and bigger than you'd ever need it, but lop off the overflow.
Here's the JSFiddle:
http://jsfiddle.net/nBAK9/4/
And here's the interesting code:
.metric:after {
position: absolute;
top: 0;
left: 50%;
margin-left: -250px; /* max expected width /2 */
content: '';
background: white;
width: 500px; /* max expected width */
height: 0;
border: 250px solid white; /* max expected width /2 */
border-top: none;
border-bottom: 50px solid #cf6; /* This size adjusts the slope of the triangle */
box-sizing: border-box;
}
Not sure you can, I played with it found that since em inherits from parents you can play a bit with it.
body{
font-size: 3em;
}
div {
width: 0;
height: 0;
border-style: solid;
border-width: 0 3em 4em 7em;
border-color: transparent transparent #007bff transparent;
-webkit-transform:rotate(360deg)
}
Fiddle
.top-arrow:before, .top-arrow:after {
position: absolute;
top: -25px;
content: '';
width: 50%;
height: 25px;
}
.top-arrow:before {
left: 0px;
background: linear-gradient(to right bottom, transparent 50%, black 50%);
}
.top-arrow:after {
right: 0px;
background: linear-gradient(to left bottom, transparent 50%, black 50%);
}
<div class="top-arrow"></div>