I need to draw the following pattern with CSS as a separator between sections of my page:
Using the skewX()
technique from this answer, I was able to mimic the triangular cutout accurately (two pseudo-elements are appended to the top of the lower section, one skewed left and one skewed right, so that the background of the upper section shows through):
But I can't figure out how to then add the border, as shown in the first image.
The problem is that the gap between the border and the lower section has to be transparent, because the background of the upper section can be a gradient, an image, etc. Therefore, I can't simply use an image for the triangular cutout, because I can't know what content will be behind it.
Is there any possible way to do this with CSS?
It is possible to do this with CSS but the only approach that I could find is a very complex one using a fair amount of gradients to mimic the borders. This couldn't be done with normal borders because that resulted in either the borders extending beyond their meeting point or the inner area never meeting. It couldn't be done with box shadow's also because the gap between the border and the filled area need to be transparent. (Not saying it cannot be done with those but just that I couldn't get it to work, maybe there is a way with those too).
The below is how I've managed to achieve the border:
The output - as you can see by hovering the element - is responsive too.
div {
position: relative;
height: 200px;
width: 300px;
background: linear-gradient(#DDD, #DDD), /* horizontal border line on left */
linear-gradient(#DDD, #DDD), /* horizontal border line on right */
linear-gradient(to top right, transparent calc(50% - 2px), #DDD calc(50% - 2px), #DDD calc(50% + 2px), transparent calc(50% + 2px)), /* angled border on left of center */
linear-gradient(to top left, transparent calc(50% - 2px), #DDD calc(50% - 2px), #DDD calc(50% + 2px), transparent calc(50% + 2px)), /* angled border on right of center */
radial-gradient(circle, #3F9CBA 0%, #153346 100%) /* actual background */;
background-size: calc(50% - 38px) 4px,
calc(50% - 38px) 4px,
40px 40px, /* size of one half of the triangle */
40px 40px, /* size of one half of the triangle */
auto auto /* size of actual bg */;
background-position: 0% calc(100% - 44px),
100% calc(100% - 44px),
calc(50% - 18px) calc(100% - 8px),
calc(50% + 18px) calc(100% - 8px),
0px 0px;
background-repeat: no-repeat;
overflow: hidden;
border-bottom: 20px solid #DDD;
}
div:before,
div:after {
position: absolute;
content: '';
height: 40px;
width: 50%;
bottom: 0;
background: #DDD;
backface-visibility: hidden;
}
div:before {
left: 0;
transform-origin: left bottom;
transform: skewX(45deg);
}
div:after {
right: 0;
transform-origin: right bottom;
transform: skewX(-45deg);
}
/* Just for demo */
div {
transition: all 1s;
}
div:hover {
height: 250px;
width: 550px;
}
<div></div>
The following is how the background properties need to be set based on the required border color and width (all calculations for 45 degree skew angle, different angle will need different calculations):
#DDD
then all color values should be changed to red.The thickness of the border will be determined using background-size
for the first two gradients and using the gradient's color-stop points for the next two gradients.
background-size
in Y-axis is nothing but the border thickness. Change it to suit the needed thickness. The background-size
in X-axis is nothing but 50% minus the height of the pseudo minus half of border thicknessbackground-position
should be set such that the required gap is there between the colored area and the border.
background-position
in X-axis should be left edge (0%) and right edge (100%) respectively. Their position in Y-axis should be above the pseudo-element and so it should be 100% minus pseudo-element's height minus the spacing.background-position
involves more complex calculation involving the border spacing, thickness and pseudo-element's height. The logic is present below.background: linear-gradient([color, [color]),
linear-gradient([color], [color]),
linear-gradient(to top right,
transparent calc(50% - [border-thickness/2]),
[color] calc(50% - [border-thickness/2]),
[color] calc(50% + [border-thickness/2]),
transparent calc(50% + [border-thickness/2])),
linear-gradient(to top left,
transparent calc(50% - [border-thickness/2]),
[color] calc(50% - [border-thickness/2]),
[color] calc(50% + [border-thickness/2]),
transparent calc(50% + [border-thickness/2])),
radial-gradient(circle, #3F9CBA 0%, #153346 100%) /* actual background */;
background-size: calc(50% - [pseudo-height - border-thickness/2]) [border-thickness],
calc(50% - [pseudo-height - border-thickness/2]) [border-thickness],
[pseudo-height] [pseudo-height],
[pseudo-height] [pseudo-height],
auto auto /* size of actual bg */;
background-position: 0% calc(100% - [pseudo-height + border-space]),
100% calc(100% - [pseudo-height + border-space]),
calc(50% - [(pseudo-height - border-space)/2]) calc(100% - [border-space + border-thickness/2]),
calc(50% + [(pseudo-height - border-space)/2]) calc(100% - [border-space + border-thickness/2]),
0px 0px;
If you need the transparent cut with border on the top part of the lower div
then you could achieve it like in the below snippet.
div {
height: 200px;
width: 300px;
}
div:nth-child(1) {
background: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
background-repeat: no-repeat;
}
div:nth-child(2) {
position: relative;
margin-top: -48px;
padding-top: 48px;
background: linear-gradient(#DDD, #DDD), linear-gradient(#DDD, #DDD), linear-gradient(to top right, transparent calc(50% - 2px), #DDD calc(50% - 2px), #DDD calc(50% + 2px), transparent calc(50% + 2px)), linear-gradient(to top left, transparent calc(50% - 2px), #DDD calc(50% - 2px), #DDD calc(50% + 2px), transparent calc(50% + 2px)), linear-gradient(#DDD, #DDD);
background-size: calc(50% - 38px) 4px, calc(50% - 38px) 4px, 40px 40px, 40px 40px, auto auto;
background-position: 0% 0px, 100% 0px, calc(50% - 18px) 0px, calc(50% + 18px) 0px, 0px 0px;
background-repeat: no-repeat;
background-clip: border-box, border-box, border-box, border-box, content-box;
overflow: hidden;
}
div:nth-child(2):before,
div:nth-child(2):after {
position: absolute;
content: '';
height: 40px;
width: 50%;
top: 8px;
background: #DDD;
backface-visibility: hidden;
}
div:before {
left: 0;
transform-origin: left bottom;
transform: skewX(45deg);
}
div:after {
right: 0;
transform-origin: right bottom;
transform: skewX(-45deg);
}
/* Just for demo */
div {
transition: all 1s;
}
body:hover > div {
height: 250px;
width: 550px;
}
<div></div>
<div></div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With