Arrows top and bottom, how to optimalise CSS? - html

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);
}
}
}
}

Related

CSS Shape with Gradient Next Adjacent to Container

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

How to make responsive to element triangle shape?

I want background shape to include triangle shape and I did it with css. I want that to be responsive in every screen size. I am stuck in this . Any advice ...
header {
width: 100%;
height:150px;
background: #eee;
}
main {
width: 100%;
height:150px;
background: #000;
position:relative;
z-index: 1;
}
main::before {
background: inherit;
top: 0;
content: '';
display: block;
height: 90%;
left: 0;
position: absolute;
right: 0;
transform: skewY(-3deg);
transform-origin: 0;
z-index: -1;
}
main::after {
border-top: 16vh solid blue;
border-left: 50vw solid transparent;
width: 0;
height: 0;
transform: skewY(-3deg);
position: absolute;
content: "";
transform-origin: 0;
right: 0;
top: -10%;
}
<header></header>
<main>
<main>
Expected result in every screen size
You can use clip-path - polygon properties for this.
The issue is, this doesn't support on IE 🤷‍♂️
More information
Mozilla: https://developer.mozilla.org/en-US/docs/Web/CSS/clip-path
W3Schools: https://www.w3schools.com/cssref/css3_pr_clip-path.asp
CSS Tricks: https://css-tricks.com/almanac/properties/c/clip-path/
main {
position: relative;
width: 100%;
height: 150px;
background: #000;
z-index: 1;
overflow: hidden;
}
main::before,
main::after {
content: '';
position: absolute;
display: block;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
z-index: 0;
}
main::before {
background-color: #00f;
-webkit-clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 0%);
clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 0%);
}
main::after {
background-color: #fff;
-webkit-clip-path: polygon(0 0, 100% 0, 100% 75%, 0 100%);
clip-path: polygon(0 0, 100% 0, 100% 75%, 0 100%);
}
<main><main>
You can try like below:
html::before {
content: "";
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 60vh;
transform-origin: right;
transform: skewY(-5deg);
background: linear-gradient(-160deg, blue 15vw, #000 15.2vw);
}
I really dont want to answer my own question though, I have been research for about two days and I found something really effective solution. So let me post it .
If I have modify a little bit on main::after property , it can be show responsively now.
transform-origin: 0; to transform-origin: -99%;
top: -10% to top: 0
That is...

How can I correctly add a shadow and a gradient to my triangular shape?

I want to make the following design:
I tried with :after and :before but it does not work. Here’s my current code:
.design {
background: #ea053a;
display: inline-block;
height: 155px;
margin-left: 33px;
margin-right: 40px;
position: relative;
width: 228px;
}
.design:before {
border-top: 43px solid #ea053a;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
margin-right: 40px;
content: "";
height: 0;
left: 0;
position: absolute;
top: 55px;
margin-top: 100px;
width: 128px;
}
<div class="design"></div>
How could I leave it the same as the original design and with the following two properties?:
box-shadow: 0 1px 10px 0 rgba(0, 0, 0, 0.2);
background-image: linear-gradient(to bottom, #ea053a, #d0021b);
Here is an idea with skew transformation and drop-shadow filter. You simply need some extra element to correctly have the gradient. The trick is to invert the skew to keep the gradient direction correct (not needed if we deal with solid color)
.box {
width: 150px;
height: 150px;
position: relative;
z-index:0;
overflow: hidden;
filter: drop-shadow(0 1px 10px rgba(0, 0, 0, 0.8));
}
.box span {
position: absolute;
z-index:-1;
top: 0;
width: 50%;
height: 100%;
overflow: hidden;
}
.box span:first-of-type {
left: 0;
transform: skewY(35deg);
transform-origin: top right;
}
.box span:last-of-type {
right: 0;
transform: skewY(-35deg);
transform-origin: top left;
}
.box span::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(to bottom, blue , red );
transform-origin: inherit;
}
.box span:first-of-type::before {
transform: skewY(-35deg);
}
.box span:last-of-type::before {
transform: skewY(35deg);
}
p {
margin:0;
color:#fff;
font-size:45px;
line-height:100px;
text-align:center;
}
<div class="box">
<span></span><span></span>
<p>29</p>
</div>
Here is how we can do with a left or right gradient. In this case we don't need extra elements because the skew will not affect the direction:
.box {
width: 150px;
height: 150px;
position: relative;
z-index:0;
overflow: hidden;
filter: drop-shadow(0 1px 10px rgba(0, 0, 0, 0.8));
}
.box:before,
.box:after{
content:"";
position: absolute;
z-index:-1;
top: 0;
width: 50%;
height: 100%;
overflow: hidden;
background:linear-gradient(to right,blue,red);
background-size:200% 100%;
}
.box:before{
left: 0;
transform: skewY(35deg);
transform-origin: top right;
}
.box:after{
right: 0;
transform: skewY(-35deg);
transform-origin: top left;
background-position:right;
}
p {
margin:0;
color:#fff;
font-size:45px;
line-height:100px;
text-align:center;
}
<div class="box">
<p>29</p>
</div>
And here is with an arbitrary gradient:
.box {
--g:linear-gradient(45deg,blue,red 60%,yellow); /* gradient coloration*/
width: 150px;
height: 150px;
margin:15px;
display:inline-block;
position: relative;
z-index:0;
overflow: hidden;
filter: drop-shadow(0 1px 10px rgba(0, 0, 0, 0.8));
}
.box span {
position: absolute;
z-index:-1;
top: 0;
width: 50%;
height: 100%;
overflow: hidden;
}
.box span:first-of-type {
left: 0;
transform: skewY(35deg);
transform-origin: top right;
}
.box span:last-of-type {
right: 0;
transform: skewY(-35deg);
transform-origin: top left;
}
.box span::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: var(--g);
background-size:200% 100%;
transform-origin: inherit;
}
.box span:first-of-type::before {
transform: skewY(-35deg);
}
.box span:last-of-type::before {
transform: skewY(35deg);
background-position:right;
}
p {
margin:0;
color:#fff;
font-size:45px;
line-height:100px;
text-align:center;
}
<div class="box">
<span></span><span></span>
<p>29</p>
</div>
<div class="box" style="--g:linear-gradient(-62deg,blue,red 60%,yellow)">
<span></span><span></span>
<p>29</p>
</div>
Since each element is taking 50% of the width we make the background to be 200% to have its size as the main container then we adjust the position to create the illusion of one background. It's like each element will show half of the main background.
An optimized version using mask
.box {
width: 150px;
height: 150px;
filter: drop-shadow(0 1px 10px rgba(0, 0, 0, 0.8));
}
.box > div {
height: 100%;
background: linear-gradient(35deg, blue, red);
-webkit-mask:
linear-gradient(#fff, #fff) top/100% 70%,
linear-gradient(to bottom right, #fff 49.5%, transparent 50%) bottom right/50% 30%,
linear-gradient(to bottom left, #fff 49.5%, transparent 50%) bottom left /50% 30%;
mask:
linear-gradient(#fff, #fff) top/100% 70%,
linear-gradient(to bottom right, #fff 49.5%, transparent 50%) bottom right/50% 30%,
linear-gradient(to bottom left, #fff 49.5%, transparent 50%) bottom left /50% 30%;
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
}
p {
margin: 0;
color: #fff;
font-size: 45px;
line-height: 100px;
text-align: center;
}
<div class="box">
<div>
<p>29</p>
</div>
</div>
Or clip-path
.box {
width: 150px;
height: 150px;
filter: drop-shadow(0 1px 10px rgba(0, 0, 0, 0.8));
}
.box > div {
height: 100%;
background: linear-gradient(35deg, blue, red);
clip-path:polygon(0 0,100% 0,100% 70%,50% 100%,0 70%);
}
p {
margin: 0;
color: #fff;
font-size: 45px;
line-height: 100px;
text-align: center;
}
<div class="box">
<div>
<p>29</p>
</div>
</div>
You can use clip-path as I did. Here is my solution.
.design {
background: #ea053a;
-webkit-clip-path: polygon(50% 0%, 100% 0, 100% 75%, 50% 100%, 0% 75%, 0 0);
clip-path: polygon(50% 0%, 100% 0, 100% 75%, 50% 100%, 0% 75%, 0 0);
height: 155px;
width: 155px;
}
.month {
text-align:center;
padding: 1rem 0 .25rem 0;
color:#fff;
font-weight:bold;
font-size: 18px;
}
.day {
text-align: center;
font-size: 60px;
font-weight:bold;
color: #fff;
}
<div class="design">
<div class="month">Diciembre</div>
<div class="day">29</div>
</div>
If you change your CSS to the following minor changes, then you can achieve the result that you have expected:
.design {
background: #ea053a;
display: inline-block;
height: 100px;
margin-left: 33px;
margin-right: 40px;
position: relative;
width: 180px;
}
.design:before {
border-top: 43px solid #ea053a;
border-left: 90px solid transparent;
border-right: 90px solid transparent;
margin-right: 40px;
content: "";
height: 0;
left: 0;
position: absolute;
top: 0px;
margin-top: 100px;
width: 0;
}
Here is the working of the above CSS:
.design {
background: #ea053a;
display: inline-block;
height: 100px;
margin-left: 33px;
margin-right: 40px;
position: relative;
width: 180px;
}
.design:before {
border-top: 43px solid #ea053a;
border-left: 90px solid transparent;
border-right: 90px solid transparent;
margin-right: 40px;
content: "";
height: 0;
left: 0;
position: absolute;
top: 0px;
margin-top: 100px;
width: 0;
}
<div class="design">
</div>
Hope this was helpful.
My Fiddle
Change to (only changed lines listed, keep everything else as-is):
.design:before {
...
border-left: 114px solid transparent;
border-right: 114px solid transparent;
...
width: 0;
}
Here is my solution to add shadow and gradient to the shape
.design {
background: #ea053a;
display: inline-block;
height: 155px;
margin-left: 33px;
margin-right: 40px;
position: relative;
width: 228px;
filter: drop-shadow(0 1px 10px rgba(0, 0, 0, 0.8));
}
.triangle {
position: absolute;
height: 100px;
top: 155px;
width: 228px;
-webkit-clip-path: polygon(49% 44%, 0% 100%, 100% 100%);
clip-path: polygon(49% 44%, 0% 100%, 100% 100%);
background-color: #ea053a;
transform: rotate(180deg);
}
<div class="design">
<div class="triangle">
</div>
</div>

CSS Animation - Having a delay when infinite animation restarts

I have an animation which I want to play infinitely to catch the users attention.
It looks like this:
http://codepen.io/anon/pen/evdqeq
What I want to achieve is, that when the corner of the "paper" is folded, it will be paused for like 3 seconds. Then the paper corner should go back. Before restarting the animation I want a 5 second delay.
I have looked up for more information about css animations but there is nothing which really fits my needs.
Do I need to switch to JavaScript?
HTML
<div id="fpc_effect-back">
<div id="fpc_box">
<div id="fpc_content">
<img src="http://www.amboss-grimma.de/wp-content/uploads/2016/12/Katalog_Amboss.png">
</div>
<div id="fpc_corner-box">
<a id="fpc_page-tip" href="#">
<div id="fpc_corner-contents">
<div id="fpc_corner-button"><strong> </strong></div><div></a>
</div>
</div>
</div>
CSS
#fpc_effect-back {
background-color: #eeeef4;
width: 0;
font: 12pt arial,sans-serif,helvetica,verdana;
color: #666;
}
#fpc_effect-back * {
box-sizing: border-box;
}
#fpc_box {
width: 197px;
position: relative;
background-color: #FFF;
}
#fpc_content {
padding: 0px;
}
#fpc_content:before {
content:"";
width: 80px;
height: 0px;
float: right;
}
#fpc_page-tip:before, #fpc_page-tip:after {
background-color: #FFF;
position: absolute;
display: block;
z-index: 2;
border-top-right-radius: 60%;
width: 50%;
height: 50%;
content: "";
}
#fpc_page-tip:before {
right: 100%;
top: 0%;
background: -webkit-radial-gradient(-180% 200%, circle, rgba(255,255,255,0) 80%, rgba(0,0,0,.2) 100%);
}
#fpc_box:hover #fpc_page-tip:before {
border-right: solid 1px #fff;
}
#fpc_box div#fpc_corner-box:hover #fpc_page-tip:before {
border-right: solid 2px #fff;
}
#fpc_page-tip:after {
top: 100%;
right: 0%;
background: -webkit-radial-gradient(-250% 320%, circle, rgba(255,255,255,0) 80%, rgba(0,0,0,.2) 100%);
}
#fpc_box:hover #fpc_page-tip:after {
border-top: solid 1px #fff;
}
#fpc_box div#fpc_corner-box:hover #fpc_page-tip:after {
border-top: solid 2px #fff;
}
#fpc_corner-box {
height: 20px;
width: 20px;
right: 0;
top: 0;
position: absolute;
overflow: visible;
animation-name: paper-corner;
animation-duration: 2s;
animation-iteration-count: infinite;
}
#fpc_box:hover #fpc_corner-box {
height: 65px;
width: 65px;
}
#fpc_box div#fpc_corner-box:hover {
}
#fpc_corner-box:before {
position: absolute;
top: 0;
right: 0;
content: "";
display: block;
width: 133%;
height: 133%;
}
#fpc_corner-contents:after {
position: absolute;
top: 0;
right: 0;
content: "";
background: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0) 37%, #DDD 62%, rgba(230, 230, 230, 0.1) 64%, rgba(255, 255, 255, 0) 67%), -webkit-radial-gradient(-50% 150%, circle, transparent 74%, rgba(0, 0, 0, 0.2) 74%, transparent 81%);
display: block;
width: 133%;
height: 133%;
}
#fpc_page-tip {
position: absolute;
top: 0;
right: 0;
content: "";
background: -webkit-linear-gradient(45deg, #ddd 17%, #dfdfdf 18%, #f5f5f5 30%, #f8f8f8 34%, #eee 39%, rgba(200,200,200,0) 41%);
display: block;
width: 100%;
height: 100%;
}
#fpc_corner-button {
position: absolute;
width: 7em;
top: 0;
right: 0;
background-color: none;
color: #fff;
font-family: Verdana, Geneva, sans-serif;
text-align: center;
padding: 8px 5px;
border-radius: 0px;
display: inline-block;
font-size: 11px;
}
#fpc_corner-contents {
width: 125%;
position: absolute;
display: block;
overflow: hidden;
-webkit-mask: -webkit-linear-gradient(45deg, transparent 49%, #000 53%);
top: 0;
right: 0;
height: 125%;
}
#fpc_corner-contents:before {
content: "";
position: absolute;
top: 0;
right: 0;
content: "";
display: block;
width: 100%;
height: 100%;
background-color: white; /* Match this background color to #fpc_effect-back */
}
#fpc_corner-box, #fpc_corner-contents, #fpc_page-tip {
-webkit-transition-property: all;
-webkit-transition-duration: .3s;
-webkit-transition-timing-function: cubic-bezier(0, 0.35, .5, 1.7);
}
#fpc_corner-button strong {
font-size: 13px;
font-weight: bold;
display: block;
}
#keyframe paper-corner{
from {height: 20px; width: 20px;}
to {height: 65px; width: 65px;}
}
#-moz-keyframes paper-corner {
from {
height:20px;
width:20px
}
to {
height:65px;
width:65px;
}
}
#-webkit-keyframes paper-corner {
from {
height:20px;
width:20px
}
to {
height:65px;
width:65px;
}
}
#keyframes paper-corner {
from {
height:20px;
width:20px
}
to {
height:65px;
width:65px;
}
}
to get the 5 second delay you need to add animation-delay:5s; to #fpc_corner-box or you can set the animation-duration: 8s;
and for the pause you can somehow achieve it using % in the animation like so:
#keyframes paper-corner {
0% {
height:20px;
width:20px
}
50% {
height:20px;
width:20px
}
60% {
height:65px;
width:65px;
}
90% {
height:65px;
width:65px;
}
100% {
height:20px;
width:20px;
}
}
Codepen demo
As i understand you can use `
setTimeout(function(){
$('#fpc_corner-box').css('animation','paper-corner 2s 1');
}, 5000); // 5000 in ms so it is 5 seconds
`
Put a longer animation-duration and add more keyframes. 0% and 100% are assumed. so it's not necessary to define them.
#fpc_corner-box {
height: 20px;
width: 20px;
right: 0;
top: 0;
position: absolute;
overflow: visible;
animation-name: paper-corner;
animation-duration: 10s; /**/
animation-iteration-count: infinite;
}
#keyframes paper-corner {
10% {
height: 65px;
width: 65px;
}
40% {
height: 65px;
width: 65px;
}
50% {
height: 20px;
width: 20px;
}
}
when the corner of the "paper" is folded, it will be paused for like 3
seconds. Then the paper corner should go back. Before restarting the
animation I want a 5 second delay.
So in total you have 3 + 5 = 8 i.e. an 8-second animation.
Easiest way would be to divide your entire animation into these 8 parts. For convenience sake, let's say 10-second animation.
First, make the animation-duration: 10s; i.e. the entire length.
Next, divide 100 by 10 and you get 10% intervals.
Now, you want a 3-second delay while starting. So, that means from 0% to 30% there is no animation. Where each 10% denotes a 1s (we divided into these chunks above). So no change in height/width.
So, your key-frames would look like this:
#keyframes paper-corner {
0% { height: 0px; width: 0px; }
30% { height: 0px; width: 0px; }
}
Next, you want end of the animation to stay for 5 seconds. Apply the same mechanism, but this time from the end. So, starting from 100% stepping 10% for each 1-second, you reach to 50% for 5-seconds. This means from 50% to 100% there is no change with width/height which is the end size.
So, your key-frames would now look like this:
#keyframes paper-corner {
0% { height: 0px; width: 0px; }
30% { height: 0px; width: 0px; }
50% { height: 65px; width: 65px; }
100% { height: 65px; width: 65px; }
}
Putting it all together in a Fiddle: https://jsfiddle.net/abhitalks/ntgtaber/
Snippet:
#fpc_effect-back {
background-color: #eeeef4;
width: 0;
font: 12pt arial, sans-serif, helvetica, verdana;
color: #666;
}
#fpc_effect-back * {
box-sizing: border-box;
}
#fpc_box {
width: 197px;
position: relative;
background-color: #FFF;
}
#fpc_content {
padding: 0px;
}
#fpc_content:before {
content: "";
width: 80px;
height: 0px;
float: right;
}
#fpc_page-tip:before,
#fpc_page-tip:after {
background-color: #FFF;
position: absolute;
display: block;
z-index: 2;
border-top-right-radius: 60%;
width: 50%;
height: 50%;
content: "";
}
#fpc_page-tip:before {
right: 100%;
top: 0%;
background: -webkit-radial-gradient(-180% 200%, circle, rgba(255, 255, 255, 0) 80%, rgba(0, 0, 0, .2) 100%);
}
#fpc_box:hover #fpc_page-tip:before {
border-right: solid 1px #fff;
}
#fpc_box div#fpc_corner-box:hover #fpc_page-tip:before {
border-right: solid 2px #fff;
}
#fpc_page-tip:after {
top: 100%;
right: 0%;
background: -webkit-radial-gradient(-250% 320%, circle, rgba(255, 255, 255, 0) 80%, rgba(0, 0, 0, .2) 100%);
}
#fpc_box:hover #fpc_page-tip:after {
border-top: solid 1px #fff;
}
#fpc_box div#fpc_corner-box:hover #fpc_page-tip:after {
border-top: solid 2px #fff;
}
#fpc_corner-box {
height: 20px;
width: 20px;
right: 0;
top: 0;
position: absolute;
overflow: visible;
animation-name: paper-corner;
animation-duration: 10s;
animation-iteration-count: infinite;
}
#fpc_box:hover #fpc_corner-box {
height: 65px;
width: 65px;
}
#fpc_box div#fpc_corner-box:hover {}
#fpc_corner-box:before {
position: absolute;
top: 0;
right: 0;
content: "";
display: block;
width: 133%;
height: 133%;
}
#fpc_corner-contents:after {
position: absolute;
top: 0;
right: 0;
content: "";
background: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0) 37%, #DDD 62%, rgba(230, 230, 230, 0.1) 64%, rgba(255, 255, 255, 0) 67%), -webkit-radial-gradient(-50% 150%, circle, transparent 74%, rgba(0, 0, 0, 0.2) 74%, transparent 81%);
display: block;
width: 133%;
height: 133%;
}
#fpc_page-tip {
position: absolute;
top: 0;
right: 0;
content: "";
background: -webkit-linear-gradient(45deg, #ddd 17%, #dfdfdf 18%, #f5f5f5 30%, #f8f8f8 34%, #eee 39%, rgba(200, 200, 200, 0) 41%);
display: block;
width: 100%;
height: 100%;
}
#fpc_corner-button {
position: absolute;
width: 7em;
top: 0;
right: 0;
background-color: none;
color: #fff;
font-family: Verdana, Geneva, sans-serif;
text-align: center;
padding: 8px 5px;
border-radius: 0px;
display: inline-block;
font-size: 11px;
}
#fpc_corner-contents {
width: 125%;
position: absolute;
display: block;
overflow: hidden;
-webkit-mask: -webkit-linear-gradient(45deg, transparent 49%, #000 53%);
top: 0;
right: 0;
height: 125%;
}
#fpc_corner-contents:before {
content: "";
position: absolute;
top: 0;
right: 0;
content: "";
display: block;
width: 100%;
height: 100%;
background-color: white;
/* Match this background color to #fpc_effect-back */
}
#fpc_corner-box,
#fpc_corner-contents,
#fpc_page-tip {
-webkit-transition-property: all;
-webkit-transition-duration: .3s;
-webkit-transition-timing-function: cubic-bezier(0, 0.35, .5, 1.7);
}
#fpc_corner-button strong {
font-size: 13px;
font-weight: bold;
display: block;
}
#keyframes paper-corner {
0% { height: 0px; width: 0px; }
30% { height: 0px; width: 0px; }
50% { height: 65px; width: 65px; }
100% { height: 65px; width: 65px; }
}
<div id="fpc_effect-back">
<div id="fpc_box">
<div id="fpc_content">
<img src="http://www.amboss-grimma.de/wp-content/uploads/2016/12/Katalog_Amboss.png" />
</div>
<div id="fpc_corner-box">
<a id="fpc_page-tip" href="#">
<div id="fpc_corner-contents">
<div id="fpc_corner-button"></div>
</div>
</a>
</div>
</div>
</div>

How can I make a div having more than 4 corners

I have to make a div using HTML and CSS only but not using any background image with more than 4 corners.
How can I do it?
You can use pseudo-element and some css shape tricks to achieve this.
.folder {
width: 190px;
height: 110px;
background: #888;
position: relative;
overflow: hidden;
}
.folder:after {
content: "";
width: 100px;
border: 15px solid transparent;
position: absolute;
right: -15px;
border-top-color: #fff;
top:0;
}
<div class="folder"></div>
There are two examples of code: with CSS ( + animation ) and SVG.
With animation
* {
box-sizing: border-box;
}
html, body {
margin: 0;
padding: 0;
position: relative;
width: 100%;
height: 100%;
background-color: #2196f3;
}
.page {
height: 100%;
display: -webkit-flex;
display: flex;
-webkit-align-items: center;
align-items: center;
-moz-box-align: center;
-webkit-box-pack: center;
-webkit-justify-content: center;
justify-content: center;
-moz-box-pack: center;
-ms-flex-pack: center;
}
.folder {
background-color: #d3eafd;
position: relative;
width: 92px;
height: 64px;
display: block;
border-top-right-radius: 8px;
border-bottom-right-radius: 8px;
border-bottom-left-radius: 8px;
}
.folder-tab {
position: absolute;
height: 10px;
left: 0;
bottom: 100%;
display: block;
width: 40%;
border-top-left-radius: 8px;
background-color: inherit;
}
.folder-tab:after {
content: '';
position: absolute;
display: block;
top: 0;
left: calc(100% - 10px);
border-bottom: 10px solid #d3eafd;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
}
.folder-icn {
padding-top: 12px;
width: 100%;
height: 100%;
display: block;
}
.downloading {
width: 30px;
height: 32px;
margin: 0 auto;
position: relative;
overflow: hidden;
}
.custom-arrow {
width: 14px;
height: 14px;
position: absolute;
top: 0;
left: 50%;
margin-left: -7px;
background-color: #fff;
-webkit-animation-name: downloading;
-webkit-animation-duration: 1.5s;
-webkit-animation-iteration-count: infinite;
animation-name: downloading;
animation-duration: 1.5s;
animation-iteration-count: infinite;
}
.custom-arrow:after {
content: '';
position: absolute;
display: block;
top: 100%;
left: -9px;
border-top: 15px solid #fff;
border-left: 16px solid transparent;
border-right: 16px solid transparent;
}
.bar {
width: 30px;
height: 4px;
background-color: #fff;
margin: 0 auto;
}
#-webkit-keyframes downloading {
0% {
top: 0;
opacity: 1;
}
50% {
top: 110%;
opacity: 0;
}
52% {
top: -110%;
opacity: 0;
}
100% {
top: 0;
opacity: 1;
}
}
#keyframes downloading {
0% {
top: 0;
opacity: 1;
}
50% {
top: 110%;
opacity: 0;
}
52% {
top: -110%;
opacity: 0;
}
100% {
top: 0;
opacity: 1;
}
}
<div class="page">
<div class="folder">
<span class="folder-tab"></span>
<div class="folder-icn">
<div class="downloading">
<span class="custom-arrow"></span>
</div>
<div class="bar"></div>
</div>
</div>
</div>
SVG
<!DOCTYPE html>
<html>
<body>
<svg height="32px" version="1.1" viewBox="0 0 32 32" width="32px" xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" xmlns:xlink="http://www.w3.org/1999/xlink"><title/><desc/><defs/><g fill="none" fill-rule="evenodd" id="Page-1" stroke="none" stroke-width="1"><g fill="#157EFB" id="icon-94-folder"><path d="M17,11 L15,7 L4.00276013,7 C2.89666625,7 2,7.88967395 2,8.991155 L2,27.008845 C2,28.1085295 2.89971268,29 3.99328744,29 L29.0067126,29 C30.1075748,29 31,28.1073772 31,27.0049107 L31,12.9950893 C31,11.8932319 30.1029399,11 28.9941413,11 L17,11 Z" id="folder"/></g></g>
</svg>
</body>
</html>
Helpful links:
More about SVG ( W3C )
The Shapes of CSS ( CSS-Tricks )
div {
width: 280px;
height: 280px;
background: #1e90ff;
-webkit-clip-path: polygon(48% 13%, 100% 13%, 100% 60%, 100% 100%, 0 100%, 0 0, 29% 0);
clip-path: polygon(48% 13%, 100% 13%, 100% 60%, 100% 100%, 0 100%, 0 0, 29% 0);
}
/* Center the demo */
html, body { height: 100%; }
body {
display: flex;
justify-content: center;
align-items: center;
}
<div></div>
With only a single block level element, you may style a :before pseudo-element to create the slanted tab above the containing <div>.
div {
margin: 40px;
width: 150px;
height: 80px;
background: red;
position: relative;
padding: 10px;
color: #fff;
}
div:before {
content:"";
position: absolute;
left: 0;
top: -20px;
width: 70px;
height: 0;
border-bottom: 20px solid red;
border-right: 20px solid transparent;
}
<div>content</div>
N.b.: This should have a better support on older browsers (and IE) than using a clip-path solution.
Just another way of doing it using the "canvas" of HTML5:
<div>
<canvas id="cnv" height="200" width="400"></canvas>
<script>
var canvas = document.getElementById('cnv');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(100, 0);
ctx.lineTo(130, 25);
ctx.lineTo(200, 25);
ctx.lineTo(200, 125);
ctx.lineTo(0, 125);
ctx.closePath();
ctx.fillStyle = "gray";
ctx.fill();
}
</script>
</div>
You can achieve this using single element and two gradients (one gradient for rectangle, another is for tab):
div {
width: 280px;
height: 200px;
background: linear-gradient(to bottom, transparent 31px, #656d78 31px),
linear-gradient(-135deg, transparent 32%, #656d78 32%);
}
<div></div>
Also this can be achieved via single gradient (for tab) using pseudoelement:
div {
width: 280px;
height: 169px;
background-color: #656d78;
margin-top: 39px;
position: relative;
}
div:after {
content: "";
position: absolute;
top: -31px;
left: 0;
width: 100%;
height: 31px;
background: linear-gradient(-135deg, transparent 50%, #656d78 50%);
}
<div></div>
If you can insert code, you could use a SVG graphic.
If not, you could draw the vector graphic css clip-path as the answer above.
There are some generators, here is one I've found
Another option is to use at least 3 divs, skew one using css transform in one of them and locating each one using relative os absolute positioning.
You can make polygon's div using CSS.
.myDiv {
-webkit-clip-path: polygon(48% 16%, 100% 16%, 100% 100%, 0% 100%, 0 0, 32% 0);
clip-path: polygon(48% 16%, 100% 16%, 100% 100%, 0% 100%, 0 0, 32% 0);
}
Or you can create any type of polygon shape (online) using this website
https://www.cssportal.com/css-clip-path-generator/