Grid shape icon - css

Writing an app that uses CSS to define icons, avoiding dependency on external image files. This works fine for circles, squares, triangles, diamonds, which is almost enough.
I wonder if it's possible to create slightly more complex icons like the two grid shaped ones on the right using CSS? It need not support IE8.
.icon {
height: 20px;
width: 20px;
background-color: steelblue;
display: inline-block;
}
.icon-circle {
border-radius: 10px;
}
.icon-square {
border-radius: 0
}
<div class="icon icon-circle"></div>

If you use pseudo elements :before and :after, you can make those icons without images. And you can even make them responsive (see my fiddle).
I used the pseudo elements to create the "white lines" so you will be able to make both last icons like this:
div {
width: 20%;
padding-bottom: 20%;
margin: 5% 10%;
background-color: #6095C9;
position: relative;
float: left;
}
div:after,
div:before {
content: "";
position: absolute;
background-color: #fff;
}
.one:before,
.two:before {
margin: 0 48%;
width: 4%;
height: 100%;
}
.one:after,
.two:after {
margin: 48% 0;
height: 4%;
width: 100%;
}
.two:before {
height: 50%;
bottom: 0;
}
<div class="one"></div>
<div class="two"></div>
FIDDLE

Here is another method to achieve the shapes using gradients instead of pseudo-elements. You can play around with the background sizes to produce different effects (like in shape3).
The advantage of this over the pseudo-element method is that it doesn't require any extra real/pseudo-elements but the drawback is that the browser support for linear-gradients is still poor compared to pseudo-elements.
div {
margin: 10px;
height: 50px;
width: 50px;
background-color: steelblue;
transition: all 1s;
}
.shape1 {
background-image: linear-gradient(to top, white 2px, transparent 2px), linear-gradient(to left, white 2px, transparent 2px);
background-size: 100% 50%, 50% 100%;
}
.shape2 {
background-image: linear-gradient(to top, white 2px, transparent 2px), linear-gradient(to left, white 2px, transparent 2px), linear-gradient(to left, white 2px, transparent 2px);
background-size: 100% 50%, 50% 50%, 100%, 100%;
background-repeat: repeat-y, repeat-x;
}
.shape3{
background-image: linear-gradient(to top, white 2px, transparent 2px), linear-gradient(to left, white 2px, transparent 2px), linear-gradient(to left, white 2px, transparent 2px);
background-size: 100% 50%, 50% 50%, 100%, 100%;
background-position: 0% 0%, 0% 100%, 0% 0%;
background-repeat: repeat-y, repeat-x;
}
.shape4 {
background-image: linear-gradient(to top, white 2px, transparent 2px), linear-gradient(to left, white 2px, transparent 2px);
background-size: 100% 25%, 25% 100%;
background-position: 0% 100%, 100% 100%;
background-repeat: repeat-y, repeat-x;
}
.large {
height: 150px;
width: 150px;
}
/* Just for demo */
div {
float: left;
}
.small{
clear:both;
}
div:hover {
background-color: crimson;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="shape1 small"></div>
<div class="shape1 large"></div>
<div class="shape2 small"></div>
<div class="shape2 large"></div>
<div class="shape3 small"></div>
<div class="shape3 large"></div>
<div class="shape4 small"></div>
<div class="shape4 large"></div>

You may be able to use a single element here without actually using pseudo elements at all with the help of box-shadow's.
So, say you have a square div element:
div {
height: 20vw;
width: 20vw;
background: tomato;
}
<div></div>
You could then add a box shadow, without a spread, by using:
div {
height: 20vw;
width: 20vw;
background: tomato;
box-shadow: 21vw 0 tomato;
}
<div></div>
you can even use multiple box shadows by seperating them with a ,:
div {
height: 20vw;
width: 20vw;
background: tomato;
box-shadow: 21vw 0 tomato, 0 21vw tomato, 21vw 21vw tomato;
}
<div></div>
You would even be able to overlap them:
div {
height: 20vw;
width: 20vw;
background: tomato;
box-shadow: 21vw 0 tomato, 0vw 21vw tomato, 16vw 21vw tomato, 21vw 21vw tomato;
}
<div></div>
So creating such wouldn't be overly taxing on browser compatibility nor pseudo elements (which could be used for other purposes).
div {
height:20vw;
width:20vw;
background:tomato;
box-shadow:0 0 0 tomato;
-webkit-animation: boxshadowmult 8s infinite;
animation: boxshadowmult 8s infinite;
}
#-webkit-keyframes boxshadowmult {
0%, 24% {
box-shadow:0 0 0 tomato;
}
25%, 49% {
height:20vw;
width:10vw;
box-shadow:11vw 0 0 tomato;
}
50%, 74% {
height:10vw;
width:10vw;
box-shadow:11vw 0 0 tomato, 6vw 11vw 0 tomato, 0 11vw 0 tomato, 11vw 11vw 0 tomato;
}
75%, 100% {
height:10vw;
width:10vw;
box-shadow:11vw 0 0 tomato, 0 11vw 0 tomato, 11vw 11vw 0 tomato;
}
}
#keyframes boxshadowmult {
0%, 24% {
box-shadow:0 0 0 tomato;
}
25%, 49% {
height:20vw;
width:10vw;
box-shadow:11vw 0 0 tomato;
}
50%, 74% {
height:10vw;
width:10vw;
box-shadow:11vw 0 0 tomato, 6vw 11vw 0 tomato, 0 11vw 0 tomato, 11vw 11vw 0 tomato;
}
75%, 100% {
height:10vw;
width:10vw;
box-shadow:11vw 0 0 tomato, 0 11vw 0 tomato, 11vw 11vw 0 tomato;
}
}
/*demo only*/
html{height:100%;
background: rgb(79,79,79); /* Old browsers */
background: -moz-radial-gradient(center, ellipse cover, rgba(79,79,79,1) 0%, rgba(34,34,34,1) 100%); /* FF3.6+ */
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(79,79,79,1)), color-stop(100%,rgba(34,34,34,1))); /* Chrome,Safari4+ */
background: -webkit-radial-gradient(center, ellipse cover, rgba(79,79,79,1) 0%,rgba(34,34,34,1) 100%); /* Chrome10+,Safari5.1+ */
background: -o-radial-gradient(center, ellipse cover, rgba(79,79,79,1) 0%,rgba(34,34,34,1) 100%); /* Opera 12+ */
background: -ms-radial-gradient(center, ellipse cover, rgba(79,79,79,1) 0%,rgba(34,34,34,1) 100%); /* IE10+ */
background: radial-gradient(ellipse at center, rgba(79,79,79,1) 0%,rgba(34,34,34,1) 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#4f4f4f', endColorstr='#222222',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
}
<div></div>

Using :before and :after, you can create two more "boxes" to play with.
JSFiddle Demo
.icon {
width: 200px;
height: 95px;
background: blue;
}
.triple-square {
position: relative;
margin: 0 0 105px 0;
border-radius: 5px;
}
.triple-square:before {
content: " ";
position: absolute;
bottom: -105px;
left: 0;
height: 95px;
width: 95px;
background: blue;
border-radius: 5px;
}
.triple-square:after {
content: " ";
position: absolute;
bottom: -105px;
right: 0;
height: 95px;
width: 95px;
background: blue;
border-radius: 5px;
}
Here's another example to create 3 circles in a triangle shape...
http://jsfiddle.net/RrhxN/1/

Related

Line with more glow in the middle than start and end

I was looking at some 80's retro design, and came across some glowy stuff, including this one:
Can this be achieved with CSS ? I mean, create a line and do some box shadow. But I have to have more glow in the middle, and less in the sides, and I am not sure how this can be accomplished in just CSS ?
Thanks in advance.
Something like this?
:root {
--clr-inner: #fed9ff;
--clr-outer: #c727c9;
}
body {
background-color: black;
text-align: center;
}
.box {
display: inline-block;
position: relative;
width: 100%;
}
.box .line-outer {
background: var(--clr-outer);
border-radius: 50%;
box-shadow: 0px 0px 25px 10px var(--clr-outer);
filter: blur(1px);
height: 4px;
overflow: hidden;
position: absolute;
width: 100%;
}
.box .line-outer .line-inner {
background: var(--clr-inner);
border-radius: 50%;
box-shadow: 0px 0px 25px 15px var(--clr-inner);
filter: blur(1px);
height: 4px;
left: 30%;
position: absolute;
top: 0;
width: 40%;
}
<div class="box">
<div class="line-outer">
<div class="line-inner"></div>
</div>
</div>
What about using a radial gradient ?
(you can adjust parameters using : https://html-css-js.com/css/generator/gradient/)
#demo {
background: #FFFFFF;
background: -moz-radial-gradient(center, #FFFFFF 0%, #A42799 64%, #000000 100%);
background: -webkit-radial-gradient(center, #FFFFFF 0%, #A42799 64%, #000000 100%);
background: radial-gradient(ellipse at center, #FFFFFF 0%, #A42799 64%, #000000 100%);
height:50px;
width:100%
}
<div id="demo"></div>

How to put gradient opacity in my gradient?

In the mockup I have, the stripes have a gradient opacity effect from transparent to semi-transparent.
Currently, I have this:
How do I make it so that the white stripes have the transparency gradient?
Here is my current code.
body {
background: gray;
}
.bar {
height: 50px;
width: 100%;
background-image: linear-gradient(90deg, #FC0252 0%, #01Fdd9 100%);
border-radius: 100rem;
position: relative;
}
/** Stripes. */
.bar::before {
content: "";
position: absolute;
border-radius: 100rem;
height: 100%;
width: 100%;
background-size: 90px 100%;
background-image: linear-gradient(
120deg,
transparent,
transparent 40%,
white 40%,
white 60%,
transparent 60%
);
}
<div class="bar"></div>
You can add a mask layer on the pseudo-element:
body {
background: gray;
}
.bar {
height: 50px;
width: 100%;
background-image: linear-gradient(90deg, #FC0252 0%, #01Fdd9 100%);
border-radius: 100rem;
position: relative;
}
/** Stripes. */
.bar::before {
content: "";
position: absolute;
border-radius: 100rem;
height: 100%;
width: 100%;
background-size: 90px 100%;
background-image: linear-gradient( 120deg, transparent 40%, white 41% 60%, transparent 61%);
-webkit-mask:linear-gradient(white,transparent);
mask:linear-gradient(white,transparent);
}
<div class="bar"></div>
In case you need better browser support than masks provide, I'd do something with an additional container, but overall it's a funny looking progress bar, hope it's for a kids game or something.
body {
background: gray;
padding-top: 5rem;
}
.bar-container {
border-radius: 100rem;
overflow: hidden;
border: darkgray 2px solid;
box-shadow: 0 2px 8px rgba(0,0,0,.5);
background-image: linear-gradient(90deg, #FC0252 0%, #01Fdd9 100%);
}
.bar {
height: 50px;
width: 100%;
position: relative;
background-size: 90px 100%;
background-image: linear-gradient(
120deg,
transparent,
transparent 40%,
white 40%,
white 60%,
transparent 60%
);
}
.bar::before, .bar::after {
content: "";
position: absolute;
top: 0;
bottom: 0;
width: 50%;
}
.bar::before {
left: 0;
background: linear-gradient(45deg, rgba(252,2,82,1) 0%, rgba(0,0,0,0) 50%);
}
.bar::after {
right: 0;
background: linear-gradient(-45deg, rgba(1,253,217,1) 0%, rgba(0,0,0,0) 50%);
}
<div class="bar-container">
<div class="bar"></div>
</div>

Make radial-gradient() span two elements

I have a circle made of two semi circular divs. I'd like to use background: radial-gradient() to make the circle appear spherical. How can I do this without overlaying the two semi-circular divs with one circular div?
[The reason for having two semi-circle divs is because of a transition in which the circle splits into two pieces. The reason for not wanting to overlay with a single div is for a similar reason]
.top-semi-circle, .bottom-semi-circle {
width: 10em;
height: 5em;
background: radial-gradient(circle at 100px 100px, red, #000);
}
.top-semi-circle {
border-radius: 10em 10em 0 0;
}
.bottom-semi-circle {
border-radius: 0 0 10em 10em;
}
.full-circle {
width: 10em;
height: 10em;
border-radius: 10em;
background: radial-gradient(circle at 100px 100px, red, #000);
}
Make this:
<div class="top-semi-circle"></div>
<div class="bottom-semi-circle"></div>
Look like this:
<div class="full-circle"></div>
Adjust the second gradient position and most important give a radius to both gradient to avoid having an automatic value that will not be the same since we will have different position and the default value of size is farthest-corner
.top-semi-circle, .bottom-semi-circle {
width: 10em;
height: 5em;
}
.top-semi-circle {
border-radius: 10em 10em 0 0;
background: radial-gradient(circle 10em at 100px 100px, red, #000);
}
.bottom-semi-circle {
border-radius: 0 0 10em 10em;
background: radial-gradient(circle 10em at 100px 20px, red, #000);
}
.bottom-semi-circle:hover {
transform:translateY(10px);
}
<div class="top-semi-circle"></div>
<div class="bottom-semi-circle"></div>
The radial gradient syntax is:
radial-gradient() = radial-gradient(
[ <ending-shape> || <size> ]? [ at <position> ]? ,
<color-stop-list>
<size>
Determines the size of the gradient’s ending shape. If omitted it defaults to farthest-corner. ref
You can also play with background-size/background-position if you want to keep the definition of the gradient the same. Simply give a size equal to the overal shape (top half + bottom half).
.top-semi-circle, .bottom-semi-circle {
width: 10em;
height: 5em;
background-image: radial-gradient(circle at 100px 100px, red, #000);
background-size:10em 10em;
}
.top-semi-circle {
border-radius: 10em 10em 0 0;
background-position:top;
}
.bottom-semi-circle {
border-radius: 0 0 10em 10em;
background-position:bottom;
}
.bottom-semi-circle:hover {
transform:translateY(10px);
}
<div class="top-semi-circle"></div>
<div class="bottom-semi-circle"></div>
Another idea is to consider overlaping with clip-path:
.top-semi-circle, .bottom-semi-circle {
width: 10em;
height: 10em;
border-radius: 10em;
background: radial-gradient(circle at 100px 100px, red, #000);
}
.top-semi-circle {
clip-path:polygon(0 0,100% 0,100% 50%,0 50%);
}
.bottom-semi-circle {
margin-top:-10em;
clip-path:polygon(0 100%,100% 100%,100% 50%,0 50%);
}
.bottom-semi-circle:hover {
transform:translateY(10px);
}
<div class="top-semi-circle"></div>
<div class="bottom-semi-circle"></div>
Same logic using mask:
.top-semi-circle, .bottom-semi-circle {
width: 10em;
height: 10em;
border-radius: 10em;
background: radial-gradient(circle at 100px 100px, red, #000);
}
.top-semi-circle {
-webkit-mask:linear-gradient(to bottom,white 50%,transparent 0);
mask:linear-gradient(to bottom,white 50%,transparent 0);
}
.bottom-semi-circle {
margin-top:-10em;
-webkit-mask:linear-gradient(to top,white 50%,transparent 0);
mask:linear-gradient(to top,white 50%,transparent 0);
}
.bottom-semi-circle:hover {
transform:translateY(10px);
}
<div class="top-semi-circle"></div>
<div class="bottom-semi-circle"></div>
This can achieved using calc() to position the radial in the second in the bottom semi-circle.
I'm using calc(100px - 5em), because 100px is the offset of the center of the gradient in the top half and 5em is the height of one semi-circle.
EDIT: I also had to specify the size of the gradient to make them match, by default the sizes are different, probably because the distance from the center and the various sides are different.
.top-semi-circle {
width: 10em;
height: 5em;
background: radial-gradient(10em at 100px 100px, red, #000);
}
.bottom-semi-circle {
width: 10em;
height: 5em;
background: radial-gradient(10em at 100px calc(100px - 5em), red, #000);
}
.top-semi-circle {
border-radius: 10em 10em 0 0;
}
.bottom-semi-circle {
border-radius: 0 0 10em 10em;
}
.full-circle {
width: 10em;
height: 10em;
border-radius: 10em;
background: radial-gradient(circle at 100px 100px, red, #000);
}
Make this:
<div class="top-semi-circle"></div>
<div class="bottom-semi-circle"></div>
Look like this:
<div class="full-circle"></div>
Use overflow hidden and pseudo elements
*{box-sizing: border-box}
[class$=circle] {
width: 10em;
height: 10em;
overflow: hidden;
position: relative;
display: block;
will-change: transform;
transition: transform .2s ease
}
[class$=circle]:before {
content: "";
position: absolute;
left: 0;
width: 10em;
height: 10em;
border-radius: 50%;
background: radial-gradient(circle at 100px 100px, red, #000);
}
[class^=top]:before {
top: 50%;
}
[class^=bottom]:before {
bottom: 50%;
}
figure{
width: 10rem;
height: 10rem;
}
figure:hover [class^=top] {
transform: translate3d(0, -10px, 0)
}
figure:hover [class^=bottom] {
transform: translate3d(0, 10px, 0)
}
<figure>
<div class="top-semi-circle"></div>
<div class="bottom-semi-circle"></div>
</figure>

Achieve object projection effect with box-shadow

I am trying to achieve this effect in CSS:
This is my code:
#test {position: relative;margin: 100px;}
#test::after {
background-color: maroon;
box-shadow: 0 -50px 10px 7px gray;
height: 45px;
left: -15px;
position: absolute;
top: 40px;
transform: perspective(150px) rotateX(-45deg);
transform-origin: center bottom 0;
width: 60px;
content: "";
}
<div id="test"></div>
but I am not achieving the expected result with the cast shadow. I wonder if its even possible to do this with CSS only?
Fiddle Demo
Maybe something like this? I added another element representing the shadow:
#shadow {
height: 90px;
left: -15px;
position: absolute;
top: 30px;
background: rgba(0, 0, 0, 0);
width: 60px;
transform: perspective(50px) rotateX(25deg);
box-shadow: 0 -106px 20px 17px #808080;
}
https://jsfiddle.net/zcyy09mp/4/
As mentioned in my comment, I would generally recommend the approach used in my fiddle (which is, use another pseudo-element) or the one in Martin's answer (which is, to use an extra element) but as you've mentioned that the other pseudo-element is already used and you are trying to avoid any extra elements, the other approach is to use gradients as background for the parent element. By using the appropriate side-to-side gradients with background-position, background-size, we can not only get the shape but also an effect very similar to the blurred nature of the shadow.
Below is a sample snippet: (the output is also reasonably responsive as you can see by hovering it)
#test {
position: relative;
height: 100px;
width: 100px;
margin: 100px;
background: linear-gradient(to bottom right, transparent 45%, gray 55%), linear-gradient(to bottom left, transparent 45%, gray 55%), linear-gradient(to bottom, transparent, gray), linear-gradient(gray, gray);
background-repeat: no-repeat;
background-size: 30px 95%, 30px 95%, calc(100% - 60px) 8px, calc(100% - 60px) calc(100% - 8px);
background-position: 0% 100%, 100% 100%, 50% 4px, 50% 100%;
}
#test::after {
position: absolute;
content: "";
background-color: maroon;
width: 100%;
height: 45%;
left: 0px;
top: 100%;
transform: perspective(150px) rotateX(-45deg);
transform-origin: center top 0;
}
/* just for demo */
#test {
transition: all 1s;
}
#test:hover {
height: 200px;
width: 200px;
}
<div id="test"></div>
In the below snippet, I have given a different color for each of the gradient just to visually show how it is achieved.
#test {
position: relative;
height: 100px;
width: 100px;
margin: 100px;
background: linear-gradient(to bottom right, transparent 45%, red 55%), linear-gradient(to bottom left, transparent 45%, blue 55%), linear-gradient(to bottom, transparent, green), linear-gradient(rebeccapurple, rebeccapurple);
background-repeat: no-repeat;
background-size: 30px 95%, 30px 95%, calc(100% - 60px) 8px, calc(100% - 60px) calc(100% - 8px);
background-position: 0% 100%, 100% 100%, 50% 4px, 50% 100%;
}
#test::after {
position: absolute;
content: "";
background-color: maroon;
width: 100%;
height: 45%;
left: 0px;
top: 100%;
transform: perspective(150px) rotateX(-45deg);
transform-origin: center top 0;
}
/* just for demo */
#test {
transition: all 1s;
}
#test:hover {
height: 200px;
width: 200px;
}
<div id="test"></div>
According to the W3 spec, "the 'box-shadow' property attaches one or more drop-shadows to the box". The shadow you want to create is not a drop shadow so there is no CSS that would make the shadow in the picture.
The closest you could achieve is pushing the shadow off one edge by using a negative spread radius:
body {
padding-top: 50px;
}
#test {
margin: 0 auto;
background-color: maroon;
box-shadow: 0 -20px 7px -6px black;
height: 45px;
width: 60px;
transform: perspective(150px) rotateX(-45deg);
transform-origin: center bottom 0;
}
<div id="test"></div>

Is it possible to give a bootstrap btn a 5 point?

I'm looking to make a bootstrap btn look a little differently with there being a 5 point at the bottom of its base. I know its possible to do shapes this way using the :before and :after tools and transform but I want to put text inside of them which is why I'm having so much trouble. Is it possible to deal directly with the btn class to make this effect happen?
You can use SkewY as shown in the demo below:
div {
height: 100px;
width: 500px;
display: inline-block;
border: 10px solid green;
border-bottom: none;
text-align: center;
line-height: 100px;
position: relative;
color: green;
font-size: 20px;
}
div:before,
div:after {
content: "";
border-bottom: 10px solid green;
position: absolute;
width: calc(50% + 10px);
height: 100%;
top: 0;
}
div:before {
transform: skewY(5deg);
left: -10px;
}
div:after {
transform: skewY(-5deg);
left: 50%;
}
<div>Request a Quote</div>
gradient can be a first chip approach ...
example in situation: http://codepen.io/gc-nomade/pen/wGEyvd
button {
color:green;
display:block;
width:50%;
margin:1em auto;
padding:1.5em 0 2.5em;
border:none;
background:linear-gradient(to left, green, green) top,
linear-gradient(to bottom, green,green) top left,
linear-gradient(to bottom, green,green) top right,
linear-gradient(to bottom left, transparent 45%, green 47%, green 51%, transparent 52%) bottom left,
linear-gradient(to bottom right, transparent 45%, green 47%, green 51%, transparent 52%) bottom right;
background-repeat:no-repeat;
background-size:100% 3px, 3px 70%, 3px 70%,50% 30%, 50% 30%;
}
<button>REQUEST A CODE</button>

Resources