Any idea how to make the div shape like this ?
Just create a rectangle and skew the Y axis using the CSS3 transform property.
In this case, transform: skewY(-20deg) will work.
.shape {
border: 2px solid;
height: 200px;
width: 100px;
transform: skewY(-20deg);
margin: 2em 0;
}
<div class="shape"></div>
This will work in all modern browsers and will fall back to a rectangle in older browsers.
.skewed {
border: solid 5px black;
height: 200px;
margin-top: 50px;
width: 100px;
transform: skewY(-30deg);
}
<div class="skewed"></div>
Related
I'm trying rotate a div with a border.
The border has the same color as the background.
A very thin line appears between the border outline and the background.
Here is my code below.
I'm trying to get rid of the weird line.
body {
background-color: black;
}
div {
width: 50px;
height: 50px;
background-color: white;
border: 50px solid black;
transform: rotate(45deg);
}
<div></div>
I tried multiple browsers.
I could fix this by using another div instead of a border, but I'm more interested in getting the border to work as expected.
A simple fix of this is by using backface-visibility: hidden.
When an element rotates, it seems that the rendering of transform: rotate() may cause the back face of it to be shown, as if in 3D perspective.
This possibly lead to the background-color of the back face (a mirror image the element's front face) overflowing the border edge in this case.
backface-visibility: hidden fix it by rendering the back face invisible, as shown in below example.
On side note, MDN did mention that backface-visibility has no effect on 2D transforms, which indicates that this behavior of transform: rotate() to have perspective is more accidental than expected.
Example:
body {
background-color: black;
display: flex;
gap: 100px;
}
div {
width: 50px;
height: 50px;
background-color: white;
border: 50px solid black;
transform: rotate(45deg);
}
div + div {
/* 👇 fixed here */
backface-visibility: hidden;
}
<div></div>
<div></div>
That's an interesting one as it only appears with the rotate transformation. You can remove it using outline to paint over the thin line with a border which will also not affect the positioning of it as follows:
body {
background-color: black;
}
div {
width: 50px;
height: 50px;
background-color: white;
border: 50px solid black;
transform: rotate(45deg);
outline-offset:-1px;
outline: 2px solid black;
}
<div></div>
Firefox only
My best guess is that there are rounding issues with the 3D rotation on the Z-axis in browser graphics functions. Rotation on the X-axis and Y-axis show no issues. It seems the size of the element drawn is rounded down (smaller), while the browser calculates with the actual or rounded up values. The difference will be a narrow gap where the element background-color is able to bleed through. I used red in the snippet to show this.
Both transform: rotate(..) and transform: rotateZ(..) show the same issue when rotation is other than 0deg (usually the purpose of rotation).
To resolve the issue (Firefox only!!) use transform-style: preserve-3d with the element being rotated.
body {
background-color: black;
padding: 3rem;
}
div {
width: 50px;
height: 50px;
background-color: red;
border: 50px solid black;
transform: rotate(45deg);
}
.test {
transform-style: preserve-3d; /* voila! background colored border is gone... */
margin-top: 4rem; /* create some distance */
}
<div></div>
<div class="test"></div>
try like below, no need border, just simply use margin.
body {
background-color: black;
}
div{
width: 50px;
height: 50px;
background-color: white;
transform: rotate(45deg);
border: 0px;
/* border: 50px solid black; */
margin: 50px;
}
<div></div>
body {
background-color: black;
}
div {
width: 50px;
height: 50px;
background-color: white;
transform: rotate(45deg);
border: 0px;
/* border: 50px solid black; */
margin: 50px;
}
<div></div>
I have tried few but is there a way to create an outline to right side of the div?
somthing like the purple line in the below image
https://unsee.cc/geduzopi/
use a pseudo element absolutely positioned to the right of the parent, then use translateX() to push it outside of the parent.
div {
display: inline-block;
width: 5em;
background: orange;
text-align: center;
position: relative;
}
div:after {
content: '';
width: .5em;
background: purple;
position: absolute;
right: 0; top: 0; bottom: 0;
transform: translateX(200%);
<div>1</div>
You can use border-right. For example
border-right: aqua 2pt solid;
See
https://www.w3schools.com/cssref/pr_border-right.asp
If you want to create an outline on one side and NOT a border, you can use box-shadow with inset like I did in my codepen example below. My example is good to look at if you have a border radius.
https://codepen.io/drewkiimon/pen/qeWQVx
div {
background: pink;
height: 250px;
width: 250px;
box-shadow: inset 0 1px black;
}
<div>
</div>
I was wondering if it is possible to make a square with round corners and a indented border in pure CSS.
Currently I have this:
#custom-square {
position: relative;
display: block;
width: 75px;
height: 75px;
border: 2px solid #8A6EF1;
border-radius: 10px;
background-color: white;
}
Considering the hassle and amount of code needed to align double curves with CSS, SVG seems way more appropriate. A few other reasons to go for svg here are :
control of the path (color, width, curve...)
control the fill with a plain color, gradient or image
less code
you can display it over a non plain background (gradient or image)
maintain the boundaries of the shape for user interactions (hover, click...)
Here is a basic example using an inline svg with a path element.
The curves are drawn with Cubic Bezier curves :
svg{width:30%;}
<svg viewbox="0 0 10 10">
<path d="M1.5 0.5 Q5 1 8.5 0.5 Q9.5 0.5 9.5 1.5 Q9 5 9.5 8.5 Q9.5 9.5 8.5 9.5 Q5 9 1.5 9.5 Q0.5 9.5 0.5 8.5 Q1 5 0.5 1.5 Q0.5 0.5 1.5 0.5z"
fill="none" stroke-width="0.2" stroke="#8A6FF2" />
</svg>
Another pure CSS approach for creating this border would be to make use of border-image property. All that is required is create an image with the required border shape and set it to an element using the border-image-source property.
.shape.large {
height: 300px;
width: 300px;
border-image-source: url(http://i.stack.imgur.com/Qkh6A.png);
border-image-width: 34px; /* the width of the border portions in the image - refer to image at the end of the answer for the exact portion details*/
border-image-slice: 34; /* equal to border-image-width */
border-width: 34px; /* equal to border-image-width */
}
.shape.small {
height: 100px;
width: 100px;
border-image-source: url(http://i.stack.imgur.com/Mra4B.png);
border-image-width: 14px;
border-image-slice: 14;
border-width: 14px;
}
.shape.small.fill {
background: aliceblue content-box;
border-image-source: url(http://i.stack.imgur.com/Ovj03.png);
border-width: 14px;
}
/* Just for demo */
body {
background: url(http://lorempixel.com/800/800/abstract/2);
}
.shape.small {
float: left;
}
.shape.large {
clear: both;
}
<div class='shape small'>Some content</div>
<div class='shape small fill'>Some content</div>
<div class='shape large'>Some content</div>
At present this method is definitely not much advantageous compared to SVG but it is an option and in my opinion is better than the other CSS only approaches that are possible.
The advantages of this approach are:
Very minimal and low complexity code.
Better control over the curves and their radii (like with SVG) because the image with the required border curvature can be created separately.
Can be placed on top of an image or a gradient background.
Can be made to degrade gracefully (into a solid square border) in browser's that don't support it.
The drawbacks are:
The container is still a square and so hover effects will not be restricted to the boundaries of the shape unlike with SVG.
Adding solid color fill to the shape is possible (by using a filled version of the image) but adding a gradient or image fill is tricky because borders are still blocks (that is, there are transparent areas on either side of the curves).
The output is responsive but as dimensions increase or decrease beyond a threshold, the shape starts to look a bit compressed or stretched. So, this is more suited for break-point based design.
The browser support is not bad but is not great either. It works in Chrome, Firefox, Safari, Opera and IE11+.
Calculation of Border Image Width:
The width or height of border area (which becomes the border-image-width) is nothing but the width of the portion highlighted in the below image.
This draft mock up is as close as i could get it to pure CSS, but still requires a nested div. You would need to tweak the sizing / radius for the before / after circles.
Pen
div {
position: absolute;
top: 100px;
left: 100px;
width: 100px;
height: 100px;
border: 4px solid purple;
border-radius: 30px;
//overflow: hidden;
box-sizing: border-box;
&:before {
position: absolute;
top: -4px;
left: -94px;
content: ' ';
width: 100px;
height: 100px;
border: 4px solid purple;
border-radius: 50px;
box-sizing: border-box;
background-color: white;
clip: rect(0px, 100px, 100px, 90px);
}
&:after {
position: absolute;
top: -4px;
right: -94px;
content: ' ';
width: 100px;
height: 100px;
border: 4px solid purple;
border-radius: 50px;
box-sizing: border-box;
background-color: white;
clip: rect(0px, 10px, 100px, 0px);
}
}
div > div {
position: absolute;
top: -4px;
left: -4px;
transform: rotate(90deg);
border-color: transparent;
}
SVG is probably the way to go here, but here's a pretty close approximation in pure CSS. It could be made even better by increasing the size of the outer circles.
#middle {
width: 96px;
height: 96px;
border-radius: 10px;
background-color: green;
border: 2px solid #8A6EF1;
}
.outside {
width: 100px;
height: 100px;
position: relative;
overflow: hidden;
margin: 0;
padding: 0;
}
.cutout {
width: 96px;
height: 96px;
border-radius: 50%;
background-color: white;
border: 2px solid #8A6EF1;
}
#top {
top: -100px;
height: 10px;
}
#right {
top: -110px;
left: 90px;
width: 10px;
}
#bottom {
top: -120px;
height: 10px;
}
#left {
top: -220px;
width: 10px;
}
#top > .cutout {
margin-top: -90px;
}
#left > .cutout {
margin-left: -90px;
}
<div id="wrapper">
<div id="middle">
</div>
<div id="top" class="outside">
<div class="cutout">
</div>
</div>
<div id="right" class="outside">
<div class="cutout">
</div>
</div>
<div id="bottom" class="outside">
<div class="cutout">
</div>
</div>
<div id="left" class="outside">
<div class="cutout">
</div>
</div>
</div>
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)
This question already has answers here:
How to bevel the corner of a block div?
(4 answers)
Closed 8 years ago.
I am trying to create a Parallelogram with a straight right side in css but so far I am struggling to achieve this.
I am using css ...
-webkit-transform: skew(-18deg);
-moz-transform: skew(-18deg);
-o-transform: skew(-18deg);
...to 'skew' the rectangle to create the Parallelogram.
I am wondering if the right side can be made straight?
Would it require :before and :after in the css?
Any help of this would be great.
Thanks,
Phil
You can achieve this by adding a triangle shaped element and positioning it next to the rectangular element.
Option 1: (Using the border hack)
In the example below, I have added a blue color for the triangular shape only to illustrate how the shape is achieved. Please replace the color in the below line to achieve the parallelogram with a slanted edge on one side and a straight edge on the other.
Change the below
border-color: transparent blue blue transparent;
to
border-color: transparent red red transparent;
Note: When using this method, it is difficult to add an extra outer border to the shape.
Snippet:
.trapezoid{
position: relative;
height: 100px;
width: 100px;
background: red;
margin-left: 50px;
color: white;
}
.trapezoid:after{
position: absolute;
content: '';
left: -50px;
top: 0px;
border-style: solid;
border-color: blue transparent blue transparent;
border-width: 100px 0px 0px 50px;
}
<div class="trapezoid">Some dummy text</div>
Option 2: (Using skew)
.trapezoid{
position: relative;
height: 100px;
width: 100px;
background: beige;
border: 1px solid red;
border-left-width: 0px;
margin-left: 50px;
}
.trapezoid:before{
position: absolute;
content: '';
left: -25px;
top: -1px;
height: 100px;
width: 50px;
background: beige;
border: 1px solid red;
z-index: -1;
-webkit-transform: skew(20deg);
-moz-transform: skew(20deg);
transform: skew(20deg);
}
<div class="trapezoid">Some dummy text.</div>
Add this id to any div youll see the expected result
#trapezoid {
border-bottom: 100px solid red;
border-left: 50px solid transparent;
height: 0;
width: 100px;
}
JSFIDDLe