I'm trying to put together a specific design for a website we are building. The header needs a parallelogram shape above it, and a trapezium to the right of the container, as shown below.
I've managed to add the parallelogram above the container, but i'm struggling to get the element to the right of the container. The following shows what i've done.
HTML
<div class="container">
<div class="row">
<div class="col">
Content Here
</div>
</div>
</div>
CSS
.container {
width: 700px;
}
.container:before {
content:'';
width: 100%;
height: 30px;
transform: skew(45deg);
background: #254896;
background: linear-gradient(90deg, #254896, #2c2b5b 100%);
display: block;
}
.row {
background: #f8f9fa;
}
.row:before {
content:'';
width: 100%;
height: 0;
border-image-source: linear-gradient(90deg, #FF0000, #940202);
border-image-slice: 1;
border-top: 30px solid red;
border-left: 30px solid transparent;
position: absolute;
left: 800px;
top: 30px;
}
.col {
background-color: #ddd;
padding: 10px;
}
https://jsfiddle.net/scarrott/vgtpna14/
The issues i'm having are:
Getting the red shape to sit neatly to the right of the container regardless of screen size.
Putting a gradient fill on the trapezium shape. If I use border-image-source it makes the shape a rectangle.
Any help would be greatly appreciated.
Here is an idea using multiple background. I used 400px instead of 700px to better see in the snippet
body {
overflow-x: hidden;
}
.container {
--w:400px;
max-width: var(--w);
position: relative;
margin: 40px auto;
}
.container:before {
content: '';
position: absolute;
top: -20px;
left: 0;
width: calc(50vw + var(--w)/2);
min-width: 100%;
height: 40px;
transform: skew(45deg);
transform-origin: top;
background:
linear-gradient(90deg, #254896, #2c2b5b 100%) top left/var(--w) 50%,
linear-gradient(90deg, #FF0000, #940202) bottom right /calc(100% - var(--w)) 50%;
background-repeat: no-repeat;
}
.row {
background: #f8f9fa;
}
.col {
padding: 10px;
}
<div class="container">
<div class="row">
<div class="col">
Content Here
</div>
</div>
</div>
Another idea with clip-path:
body {
overflow-x: hidden;
}
.container {
--w:400px;
max-width: var(--w);
position: relative;
margin: 40px auto;
}
.container:before {
content: '';
position: absolute;
top: -20px;
left: 0;
width: calc(50vw + var(--w)/2);
min-width: 100%;
height: 40px;
clip-path:polygon(0 0, calc(var(--w) - 20px) 0,var(--w) 50%,100% 50%,100% 100%,calc(var(--w) + 20px) 100%,var(--w) 50%, 20px 50%);
background:
linear-gradient(90deg, #254896, #2c2b5b 100%) top left/var(--w) 50%,
linear-gradient(90deg, #FF0000, #940202) bottom right /calc(100% - var(--w)) 50%;
background-repeat: no-repeat;
}
.row {
background: #f8f9fa;
}
.col {
padding: 10px;
}
<div class="container">
<div class="row">
<div class="col">
Content Here
</div>
</div>
</div>
Including bootstrap
body {
overflow-x: hidden;
}
.container {
--w: 540px;
position: relative;
margin-top: 40px;
}
#media (min-width: 768px) {
.container {
--w: 720px;
}
}
#media (min-width: 992px) {
.container {
--w: 960px;
}
}
#media (min-width: 1200px) {
.container {
--w: 1140px;
}
}
.container:before {
content: '';
position: absolute;
top: -20px;
left: 0;
width: calc(50vw + var(--w)/2);
min-width: 100%;
height: 40px;
clip-path: polygon(0 0, calc(var(--w) - 20px) 0, var(--w) 50%, 100% 50%, 100% 100%, calc(var(--w) + 20px) 100%, var(--w) 50%, 20px 50%);
background:
linear-gradient(90deg, #254896, #2c2b5b 100%) top left/var(--w) 50%,
linear-gradient(90deg, #FF0000, #940202) bottom right /calc(100% - var(--w)) 50%;
background-repeat: no-repeat;
}
.row {
background: #f8f9fa;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<div class="container">
<div class="row">
<div class="col">
Content Here
</div>
</div>
</div>
Another approach would be to to have the 2 parallelogram shapes inside the container div with specified percentages.
.row::before {
content: '';
width: calc(70% - 14px);
height: 30px;
transform: skew(45deg);
background: #254896;
background: linear-gradient(90deg, #254896, #2c2b5b 100%);
}
.row::after {
content: '';
width: calc(30% - 14px);
height: 30px;
position: absolute;
right: 0;
top: 30px;
transform: skew(45deg);
background: red;
background: linear-gradient(90deg, #FF0000, #940202);
}
jsFiddle
Related
I want to stack two colors one on top of the other. I did it by creating and sovrapposing two divs, having the one on the top with an opacity of 60%.
I wonder if there's a simpler way requiring only one div with two colors or maybe just one color that is a mix of the two.
I post here my code, If you notice any bad practice let me know please. I am eager to improve my skills.
* {
padding: 0;
margin: 0;
border: 0;
box-sizing: border-box;
}
/* ~~~~~~~~~~SKY~~~~~~~~~~ */
#sky {
position: relative;
z-index: -100;
width: 100vw;
height: 100vh;
background-image: linear-gradient( to top, midnightblue, black);
}
/* ~~~~~~~~~~MOON~~~~~~~~~~ */
.moon {
position: absolute;
top: 3%;
right: 0%;
width: 200px;
height: 200px;
border-radius: 50%;
}
#dark-moon {
background-color: silver;
}
#light-moon {
background-color: goldenrod;
background-image: radial-gradient(dimgrey 20%, transparent 16%), radial-gradient(dimgrey 15%, transparent 16%);
background-size: 60px 60px;
background-position: 0 0, 30px 30px;
opacity: 60%;
}
/* ~~~~~~~~~~SEA~~~~~~~~~~ */
#sea {
position: absolute;
bottom: 0%;
width: 100vw;
height: 25vh;
background-color: #48B;
}
<div id="sky">
<div id="dark-moon" class="moon"></div>
<div id="light-moon" class="moon"></div>
</div>
<div id="sea"></div>
As you can see there's a golden moon over a silver one. How can I get the same result having only one moon?
You can do it with 0 elements using pseudo element and multiple backgrounds:
html {
min-height: 100%;
background: linear-gradient( to top, midnightblue, black);
}
html::before {
content:"";
position: absolute;
top: 3%;
right: 0;
width: 200px;
height: 200px;
border-radius: 50%;
background:
linear-gradient(rgba(192,192,192,0.4) 0 0),
radial-gradient(dimgrey 20%, transparent 16%),
radial-gradient(dimgrey 15%, transparent 16%) 30px 30px,
goldenrod;
background-size: 60px 60px;
}
html::after {
content:"";
position: absolute;
bottom: 0;
left:0;
right:0;
height: 25vh;
background: #48B;
}
Another fancy idea to optimize the code more:
html {
min-height: 100%;
background:
linear-gradient(#48B 0 0) bottom/100% 25vh no-repeat fixed,
linear-gradient(black,midnightblue);
}
html::before {
content:"";
position: absolute;
top: 3%;
right: 0;
width: 200px;
height: 200px;
border-radius: 50%;
background:
linear-gradient(#48B 0 0) bottom/100% 25vh no-repeat fixed,
linear-gradient(rgba(192,192,192,0.4) 0 0),
radial-gradient(dimgrey 20%, transparent 16%) 0 0 /60px 60px,
radial-gradient(dimgrey 15%, transparent 16%) 30px 30px/60px 60px,
goldenrod;
}
Another option that only involves setting one background property would be to "stretch and displace" a linear-gradient in such a way that the result is a single color.
--base-col and --blend-col defines the gradient, --blend-amount sets the color mix, and --stretch-factor determines how much stretch is applied to the gradient:
* {
padding: 0;
margin: 0;
border: 0;
box-sizing: border-box;
}
/* ~~~~~~~~~~SKY~~~~~~~~~~ */
#sky {
position: relative;
z-index: -100;
width: 100vw;
height: 100vh;
background-image: linear-gradient( to top, midnightblue, black);
}
/* ~~~~~~~~~~MOON~~~~~~~~~~ */
.moon {
position: absolute;
top: 3%;
right: 0%;
width: 200px;
height: 200px;
border-radius: 50%;
}
#dark-moon {
--blend-amount: 60%;
--base-col: silver;
--blend-col: goldenrod;
--stretch-factor: 100;
background: linear-gradient(
var(--base-col) calc(( 0% - var(--blend-amount)) * var(--stretch-factor)),
var(--blend-col) calc((100% - var(--blend-amount)) * var(--stretch-factor))
);
}
#light-moon {
background-image: radial-gradient(dimgrey 20%, transparent 16%), radial-gradient(dimgrey 15%, transparent 16%);
background-size: 60px 60px;
background-position: 0 0, 30px 30px;
}
/* ~~~~~~~~~~SEA~~~~~~~~~~ */
#sea {
position: absolute;
bottom: 0%;
width: 100vw;
height: 25vh;
background-color: #48B;
}
<div id="sky">
<div id="dark-moon" class="moon"></div>
<div id="light-moon" class="moon"></div>
</div>
<div id="sea"></div>
You can try to get the hex code for the mixed color first using online color mixer tool such as this one https://colordesigner.io/color-mixer. After that you can use the result color in one div.
the result I need to get:
what i have so far
header {
min-height: 300px;
background: #000;
}
main {
position: relative;
width: 100%;
overflow: hidden;
min-height: 300px;
}
main:before {
content: '';
position: absolute;
background: #000;
top: 0;
left: 0;
width: 100%;
height: 200px;
}
main:after {
content: '';
position: absolute;
top: 0rem;
background: #141f36;
width: 120%;
height: 300px;
margin-left: -10%;
margin-right: 10%;
border-radius: 200vh 200vh 0% 0% / 20vh 20vh 0% 0%;
}
<div class="page">
<header></header>
<main></main>
</div>
I have no idea how to make the line, can someone help me with this?
NOTE: the line needs to have blur/bright/light effect just like in the example image
Here is a single div idea with radial-gradients.
div {
min-height: 400px;
width: 100%;
/* you can change these variables to see what they do */
--top-distance: 3%;
--line-width: 0.3%;
--blur: 0.5%;
--gradient-top-distance: 100px;
--s: 350%; /* increase this to reduce the slope. */
background: radial-gradient(farthest-side at center bottom, transparent 0 calc(100% - (var(--top-distance) + var(--blur)*2 + var(--line-width))), #0c5dd3 calc(100% - (var(--top-distance) + var(--blur) + var(--line-width))) calc(100% - (var(--top-distance) + var(--blur))), transparent calc(100% - var(--top-distance)) 100%) 50% calc(100% + var(--gradient-top-distance))/var(--s) 100% no-repeat,
radial-gradient(farthest-side at center bottom, #141f36 99%, transparent 100%) 50% calc(100% + var(--gradient-top-distance))/var(--s) 100% no-repeat;
background-color: #000;
}
<div></div>
You can add another pseudo element where you apply a blur filter
main {
position: relative;
overflow: hidden;
min-height: 400px;
background: #000;
}
main:before,
main:after{
content: '';
position: absolute;
height:300px;
background: #141f36;
left:-10%;
right:-10%;
bottom:0;
border-radius: 200vh 200vh 0% 0% / 20vh 20vh 0% 0%;
}
main:after {
border:3px solid #0c5dd3;
filter:blur(1px);
bottom:-22px;
background:none;
}
<main></main>
Please see the image below for what I am trying to create:
I have the following so far but it needs to be more ''frequent'' like increasing the frequency rate of a sin or cosine wave.
#wave {
position: relative;
height: 70px;
width: 600px;
background: #e0efe3;
}
#wave:before {
content: "";
display: block;
position: absolute;
border-radius: 100% 50%;
width: 340px;
height: 80px;
background-color: white;
right: -5px;
top: 40px;
}
#wave:after {
content: "";
display: block;
position: absolute;
border-radius: 100% 50%;
width: 300px;
height: 70px;
background-color: #e0efe3;
left: 0;
top: 27px;
}
<div id="wave"></div>
I have an online generator for the below code: https://css-generators.com/wavy-shapes/
Here is an idea with radial-gradient and CSS variables where you can easily control the shape:
.wave {
--c:red; /* Color */
--t:5px; /* Thickness */
--h:50px; /* Height (vertical distance between two curve) */
--w:120px; /* Width */
--p:13px; /* adjust this to correct the position when changing the other values*/
background:
radial-gradient(farthest-side at 50% calc(100% + var(--p)), #0000 47%, var(--c) 50% calc(50% + var(--t)),transparent calc(52% + var(--t))),
radial-gradient(farthest-side at 50% calc(0% - var(--p)), #0000 47%, var(--c) 50% calc(50% + var(--t)),transparent calc(52% + var(--t)));
background-size: var(--w) var(--h);
background-position: calc(var(--w)/2) calc(var(--h)/2),0px calc(var(--h)/2);
border:1px solid;
margin:5px 0;
display:inline-block;
width:300px;
height:150px;
}
<div class="wave"></div>
<div class="wave" style="--w:200px;--h:40px;--p:10px; --t:8px;--c:purple"></div>
<div class="wave" style="--w:80px ;--h:20px;--p:5px; --t:3px;--c:blue;"></div>
<div class="wave" style="--w:100px;--h:30px;--p:14px;--t:10px;--c:green;"></div>
Here is a Codepen to play with the code
My problem is that I want to display 'arrows' above and below certain sections (which I have given classes of course).
These arrows can be both bottom, top and you can pick left and right for both the bottom and top arrow:
I made a snippet to demonstrate, but wasn't able to insert the SVG properly, so have replaced that code with background: red;.
The problem with above code is that it uses a wildcard selector on the classes, so it might interfere. So I would prefer something like class="arrow arrow-top arrow-left". However, that gives a problem when you add two arrows to one section: class="arrow arrow-top arrow-left arrow-bottom arrow-right".
Any suggestions on how to optimise this code?
[class*=arrow]:before, [class*=arrow]:after {
content: '';
display: none;
position: absolute;
left: 0;
right: 0;
height: 50px;
height: 12vw;
width: 100%;
//background-image: url("arrow.svg#svgView(preserveAspectRatio(none))");
background-color: red;
background-size: 100% 100%;
}
[class*=arrow-top] {
padding-top: 50px;
padding-top: 12vw;
}
[class*=arrow-bottom] {
padding-bottom: 50px;
padding-bottom: 12vw;
}
.arrow-top-left:before {
display: block;
top: 0;
}
.arrow-top-right:before {
display: block;
top: 0;
transform: scaleX(-1);
}
.arrow-bottom-left:after {
display: block;
bottom: 0;
transform: scaleY(-1);
}
.arrow-bottom-right:after {
display: block;
bottom: 0;
transform: scale(-1, -1);
}
/* unessential code */
section {
background-color: #EC644B;
height: 300px;
position: relative;
}
section:nth-child(odd) {
background-color: #DCC6E0;
}
p {
padding: 20px;
}
<section class="arrow arrow-top arrow-bottom-left">
<p>Een prachtige sectie</p>
</section>
<section class="arrow-top-right arrow-bottom-right">
<p>Een prachtige sectie</p>
</section>
<section class="arrow-bottom-right">
<p>Een prachtige sectie</p>
</section>
I would consider linear-gradient and you can easily achieve this by having two classes for each arrow that you can combine:
.top-arrow,.bottom-arrow {
margin:5px;
min-height:200px;
max-width:400px;
position:relative;
z-index:0;
border:1px solid;
}
.top-arrow:before,
.bottom-arrow:after{
content:"";
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
}
.top-arrow:before {
background:
linear-gradient(to top right,transparent 50%,red 50.5%) top left/20% 50% no-repeat,
linear-gradient(to top left,transparent 50%,red 50.5%) top right/80% 50.5% no-repeat;
}
.bottom-arrow:after {
background:
linear-gradient(to bottom right,transparent 50%,pink 50.5%) bottom left /80% 50% no-repeat,
linear-gradient(to bottom left,transparent 50%,pink 50.5%) bottom right /20% 50.5% no-repeat;
}
<div class="top-arrow bottom-arrow">
</div>
<div class="bottom-arrow">
</div>
<div class="top-arrow">
</div>
Why not use CSS clip-path's to create the shapes you want within you :before's and :after's.
You will get a slick outcome, with solid corners and it will also be very easy to change their shape to your desires.
clip-path - CSS | MDN
CanIUse Support
clip-path Generator
body {
margin: 0;
padding: 0;
}
section {
padding: 30px;
height: 300px;
width: 100%;
background: #EC644B;
position: relative;
}
section:nth-child(odd) {
background: #DCC6E0
}
.arrow-top-left,
.arrow-top-right {
padding-top: 80px;
}
.arrow-top-left:before,
.arrow-top-right:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 80px;
background: blue;
}
.arrow-top-left:before {
-webkit-clip-path: polygon(20% 100%, 0 0, 100% 0);
clip-path: polygon(20% 100%, 0 0, 100% 0);
}
.arrow-top-right:before {
-webkit-clip-path: polygon(80% 100%, 0 0, 100% 0);
clip-path: polygon(80% 100%, 0 0, 100% 0);
}
.arrow-bottom-left,
.arrow-bottom-right {
padding-bottom: 80px;
}
.arrow-bottom-left:after,
.arrow-bottom-right:after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 80px;
background: green;
}
.arrow-bottom-left:after {
-webkit-clip-path: polygon(20% 0, 0% 100%, 100% 100%);
clip-path: polygon(20% 0, 0% 100%, 100% 100%);
}
.arrow-bottom-right:after {
-webkit-clip-path: polygon(80% 0, 0% 100%, 100% 100%);
clip-path: polygon(80% 0, 0% 100%, 100% 100%);
}
<section class="arrow-top-left arrow-bottom-right">
</section>
<section class="arrow-bottom-right">
</section>
<section class="arrow-top-right">
</section>
A colleague thought about this and came up with this SASS-solution:
.u-arrow {
&-top,
&-bottom {
&-right,
&-left {
position: relative;
&:before,
&:after {
z-index: 0;
content: '';
display: none;
position: absolute;
left: 0;
right: 0;
height: 50px;
height: 12vw;
width: 100%;
background-size: 100% 100%;
background-image: url("/dist/images/arrow-white-mobile.svg");
.u-bg-blue & {
background-image: url("/dist/images/arrow-blue-mobile.svg");
}
#media (min-width: $screen-sm) {
background-image: url("/dist/images/arrow-white.svg");
.u-bg-blue & {
background-image: url("/dist/images/arrow-blue.svg");
}
}
#media (min-width: 1200px) {
height: 150px;
}
}
}
}
&-top {
&-left,
&-right {
padding-top: 50px;
padding-top: 12vw;
#media (min-width: 1200px) {
padding-top: 150px;
}
&:before {
display: block;
top: 0;
}
}
&-right {
&:before {
transform: scaleX(-1);
}
}
}
&-bottom {
&-left,
&-right {
padding-bottom: 50px;
padding-bottom: 12vw;
#media (min-width: 1200px) {
padding-bottom: 150px;
}
&:after {
display: block;
bottom: 0;
}
}
&-left {
&:after {
transform: scaleY(-1);
}
}
&-right {
&:after {
transform: scale(-1, -1);
}
}
}
}
I'm trying to create transparent div full width and height around 500px using borders but i have trouble with creating this kind of curved shape.
It should look like on the example image, the yellow shape.
.transparent_bg {
width: 100%;
height: 485px;
background: transparent;
border:solid 5px #000;
border-color:#000 transparent transparent transparent;
border-radius: 50%/200px 200px 0 0;
transform: rotate(180deg);
position: relative;
overflow:hidden;
}
.transparent_bg:after {
content: "";
width: 100%;
height: 485px;
position: absolute;
top: 0;
background: red;
}
<div class="transparent_bg"></div>
I have included a link to my work until this moment but without success.
You can use clip path in both ways (on the top element or the bottom one) and simply make top and bottom to overlay like this :
.first,
.second {
display: inline-block;
margin: 5px;
}
.first .top {
clip-path: circle(72.9% at 50% 27%);
height: 200px;
width: 200px;
background: url(https://picsum.photos/id/10/800/800) center/cover;
position: relative;
}
.first .bottom {
margin-top: -70px;
background: yellow;
height: 100px;
width: 200px;
}
.second .top {
height: 200px;
width: 200px;
background:url(https://picsum.photos/id/10/800/800) center/cover;
position: relative;
}
.second .bottom {
clip-path: polygon(0 25%, 14% 41%, 28% 51%, 49% 54%, 66% 53%, 79% 48%, 89% 39%, 100% 27%, 100% 100%, 47% 100%, 0% 100%);
margin-top: -70px;
background: yellow;
height: 100px;
width: 200px;
}
<div class="first">
<div class="top">
</div>
<div class="bottom">
</div>
</div>
<div class="second">
<div class="top">
</div>
<div class="bottom">
</div>
</div>
Here is a useful link to generate path :
https://bennettfeely.com/clippy/
Here is another idea using radial-gradient
.first {
height: 200px;
width: 400px;
background:
radial-gradient(100% 100% at top, #0000 60%, yellow 61%),
url(https://picsum.photos/id/10/800/800) center/cover;
}
<div class="first">
</div>
Using mask if you want transparency:
.first {
height: 200px;
width: 400px;
background: url(https://picsum.photos/id/10/800/800) center/cover;
-webkit-mask:radial-gradient(100% 100% at top, #fff 60%, #0000 61%);
mask:radial-gradient(100% 100% at top, #fff 60%, #0000 61%);
}
.bottom {
-webkit-mask:radial-gradient(100% 100% at top, #0000 60%, #fff 61%);
mask:radial-gradient(100% 100% at top, #0000 60%, #fff 61%);
}
body {
background:yellow;
}
<div class="first">
</div>
<div class="first bottom">
</div>
If you want to overlay top and bottom, just use clip path both ways (on the top or bottom element).`
.transparent_bg {
width: 100%;
height: 485px;
background: transparent;
border-top-left-radius: 50% 50%;
border-top-right-radius: 50% 50%;
transform: rotate(180deg);
position: relative;
overflow:hidden;
}
.transparent_bg:after {
content: "";
width: 100%;
height: 485px;
position: absolute;
top: 0;
background: red;
}
.transparent_bg {
width: 100%;
height: 485px;
background: transparent;
border-top-left-radius: 50% 50%;
border-top-right-radius: 50% 50%;
transform: rotate(180deg);
position: relative;
overflow:hidden;
}
.transparent_bg:after {
content: "";
width: 100%;
height: 485px;
position: absolute;
top: 0;
background: red;
}
<div class="transparent_bg"></div>