White border on overlap CSS - html

Can this be created using CSS :
I have tried using PNG images :
.x {
position:relative;
top: 100px;
left: 0px;
height: 120px;
width: 300px;
display: block;
}
.y {
position:relative;
top: -20px;
left: 0px;
height: 120px;
width: 300px;
display: block;
transform: rotate(60deg);
}
.z {
position:relative;
top: -140px;
left: 0px;
height: 120px;
width: 300px;
display: block;
transform:rotate(-60deg)
}
<img class="x" src="http://i.stack.imgur.com/Qf8Ot.png">
<img class="y" src="http://i.stack.imgur.com/Qf8Ot.png">
<img class="z" src="http://i.stack.imgur.com/Qf8Ot.png">
But I wanted overlap to be white as the first image. Any clues? Thank you very much.

Create ellipses using border-radius.
Add box-shadow to them :
#a, #a:before, #a:after {
height:80px;
width: 300px;
background: transparent;
border-radius: 50%;
border: 5px solid black;
transform: rotate(30deg);
}
#a {
position: relative;
top:100px;
}
#a:before, #a:after {
position: absolute;
content: "";
box-shadow:inset 0 0 0 4px white, 0 0 0 4px white;
}
#a:before {
transform: rotate(60deg);
}
#a:after {
transform: rotate(120deg);
}
<div id="a"></div>

You should use box-shadow. Make the color of shadow white.
Use inset shadow also, it will make shadow inside the image.
box-shadow :inset 0 0 5px #FFF, 0 0 5px #FFF ;
use -webkit-, -moz- , -o- according to your browser requirments.

Related

How would I construct a speech bubble strictly with a border similar to the graphic shown? [duplicate]

I have a project where I need to insert speech bubbles / message boxes. The general shape I am trying to achieve is this one :
.bubble {
height: 100px;
width: 200px;
border: 3px solid gray;
background: lightgray;
position: relative;
cursor:pointer;
}
.triangle {
width: 0;
border-top: 20px solid black;
border-left: 20px solid transparent;
border-right: 20px solid transparent;
cursor:pointer;
}
<div class="bubble">Speech bubble
</div>
<div class="triangle">
</div>
This currently does not pass a hit-test as the transparent border is also clickable.
Objectives
The hit box (clickable / hoverable areas) needs to stick to the shape's boundaries (the transparent borders here are also hoverable, invalidating this).
I need to display the shape over various content (images, gradents, text...),
Issues
The main issues I am having when manipulating this shape are:
Have the ability to move the triangle around the speech bubble according to the position of the element it refers to (top/left/right/bottom sides)
adding a border or box shadow around it when emphasis is needed
Is there anyway of addressing these issues?
In order to achieve this, you should consider altering your markup in order to make your html more efficient. This can be achieved using a pseudo element. I'll address each point individually, and put it all together at the end of my answer.
First of all,
Use pseudo elements to avoid extra elements
You could use a pseudo element to remove the extra .triangle div. This not only reduces your div numbers, but also helps with positioning as you can use the top: left: right: and bottom: css properties in order to position according to your main element. This can be seen below:
.oneAndOnlyDiv {
height: 100px;
width: 200px;
border: 3px solid gray;
background: lightgray;
position: relative;
}
.oneAndOnlyDiv:before {
content: "";
position: absolute;
top: 100%;
left: 20px;
width: 0;
border-top: 20px solid black;
border-left: 20px solid transparent;
border-right: 20px solid transparent;
}
<div class="oneAndOnlyDiv">Main div</div>
Hit testing
In order to create your "hit test", you may wish to use a rotated element instead of a border hack.
Something like:
div {
height: 100px;
width: 200px;
background: gray;
position: relative;
cursor:pointer;
}
div:before {
content: "";
position: absolute;
top: 100%;
left: 20px;
height: 20px;
width: 20px;
background: black;
transform: rotate(45deg);
transform-origin:top right;
}
<div>Only element</div>
or use a skewed pseudo element:
div {
height: 100px;
width: 200px;
background: gray;
position: relative;
cursor:pointer;
}
div:before {
content: "";
position: absolute;
top: 90%;
left: 20px;
height: 30%;
width: 20px;
background: black;
transform: skewY(-45deg);
transform-origin:bottom left;
z-index:-1;
}
<div>Only element</div>
which will show the pointer only when the square or main element is hovered.
But hang on, that messes up the positioning? how can you deal with that?
There are a few solutions to that. One of which is to use the calc CSS property.
div {
height: 100px;
width: 200px;
background: gray;
position: relative;
cursor:pointer;
}
div:before {
content: "";
position: absolute;
top: -webkit-calc(100% - 10px); /*may require prefix for old browser support*/
top: calc(100% - 10px); /*i.e. half the height*/
left: 20px;
height: 20px;
width: 20px;
background: gray;
transform: rotate(45deg);
}
<div>Only element</div>
Adding a border
You can add a border quite easily now, simply by adding a border declaration to the main element, and setting the border-bottom and border-right of the pseudo element to inherit
Border
div {
height: 100px;
width: 200px;
background: gray;
position: relative;
cursor:pointer;
border:3px double black;
}
div:before {
content: "";
position: absolute;
top: -webkit-calc(100% - 10px); /*may require prefix for old browser support*/
top: calc(100% - 10px); /*i.e. half the height*/
left: 20px;
height: 20px;
width: 20px;
background: gray;
transform: rotate(45deg);
border-bottom:inherit;
border-right:inherit;
box-shadow:inherit;
}
<div>Only element</div>
Box Shadow:
In order to have a box shadow, I've used the :after pseudo element in order to hide the box shadow over the other pseudo, making the element seem as one single element.
div {
height: 100px;
width: 200px;
background: gray;
position: relative;
cursor:pointer;
box-shadow: 5px 5px 10px 2px black;
}
div:before,div:after {
content: "";
position: absolute;
top: -webkit-calc(100% - 10px); /*may require prefix for old browser support*/
top: calc(100% - 10px); /*i.e. half the height*/
left: 20px;
height: 20px;
width: 20px;
background: gray;
transform: rotate(45deg);
z-index:-1;
box-shadow:inherit;
}
div:after{
box-shadow:none;
z-index:8;
}
<div>Only element</div>
Putting it all together
You can also add a border radius to your message box or speech bubble by again, using the border-radius property:
div {
height: 100px;
width: 200px;
background: gray;
position: relative;
cursor:pointer;
border:3px double black;
border-radius:10px;
}
div:before {
content: "";
position: absolute;
top: -webkit-calc(100% - 10px); /*may require prefix for old browser support*/
top: calc(100% - 10px); /*i.e. half the height*/
left: 20px;
height: 20px;
width: 20px;
background: gray;
transform: rotate(45deg);
border-bottom:inherit;
border-right:inherit;
box-shadow:inherit;
}
<div>Only element</div>
This even allows you to create not only a triangle, but how about a circle instead?
div {
height: 100px;
width: 200px;
background: gray;
position: relative;
cursor:pointer;
border:3px double black;
border-radius:10px;
}
div:before {
content: "";
position: absolute;
top: -webkit-calc(100% - 13px); /*may require prefix for old browser support*/
top: calc(100% - 13px); /*i.e. half the height + border*/
left: 20px;
height: 20px;
width: 20px;
background: gray;
transform: rotate(45deg);
border:3px double transparent;
border-bottom:inherit;
border-right:inherit;
box-shadow:inherit;
border-radius:50%;
}
<div>Only element</div>
If you are having issues with content overflowing and being 'hidden' behind this pseudo element, and you aren't fussed about having a border, you could use a negative z-index which will solve this issue.
Don't like using 'magic numbers'?
If you don't like the idea of using a calc value, in which the positioning in my answer is currently using (whilst working), you may wish to use transform:translate(50%)
This would be a much better approach, since:
You do not need to know the size of the border, nor half the width
You will be making your message box/ bubble a lot more dynamic in its positioning, and would support further sizings.
div {
height: 100px;
width: 200px;
background: gray;
position: relative;
cursor: pointer;
border: 3px double black;
border-radius: 10px;
}
div:before {
content: "";
position: absolute;
top: 100%;
left: 30px;
height: 20px;
width: 20px;
background: gray;
box-sizing:border-box;
transform: rotate(45deg) translate(-50%);
border-bottom: inherit;
border-right: inherit;
box-shadow: inherit;
}
<div>Only element</div>
Want to move it? You can!
div {
height: 100px;
width: 200px;
background: gray;
position: relative;
cursor: pointer;
border: 3px double black;
border-radius: 10px;
}
div:before {
content: "";
position: absolute;
top: 100%;
left: 10%;
height: 20px;
width: 20px;
background: gray;
box-sizing: border-box;
transform: rotate(45deg) translate(-50%);
border-bottom: inherit;
border-right: inherit;
box-shadow: inherit;
transition: all 0.8s;
}
div:hover:before {
left: 90%;
}
<div>Only element</div>
Want it one the right?
div {
height: 100px;
width: 200px;
background: gray;
position: relative;
cursor: pointer;
border: 3px double black;
border-radius: 10px;
}
div:before {
content: "";
position: absolute;
top: 15%;
left: 100%;
height: 20px;
width: 20px;
background: gray;
box-sizing:border-box;
transform: rotate(45deg) translate(-50%);
border-top: inherit;
border-right: inherit;
box-shadow: inherit;
transition:all 0.8s;
}
div:hover:before{
top:80%;
}
<div>Only Element</div>
Want it to be a different shape of triangle?
div {
height: 100px;
width: 200px;
background: gray;
position: relative;
cursor: pointer;
border-radius: 10px;
}
div:before {
content: "";
position: absolute;
top: 70%;
left: 100%;
height: 20px;
width: 20px;
background: gray;
box-sizing:border-box;
transform: translate(-50%) skewX(45deg);
box-shadow: inherit;
transition:all 0.8s;
z-index:-1;
}
div:hover:before{
transform: translate(-50%);
border-radius:50%;
top:20%;
}
<div>Only Element</div>
We can rely on clip-path and drop-shadow filter to easily achieve this:
.box {
margin: 50px;
width: 200px;
height: 100px;
border-radius: 15px;
background: red;
position: relative;
filter: /* the more shadow you add the thicker the border will be */
drop-shadow(0px 0px 1px green)
drop-shadow(0px 0px 1px green)
drop-shadow(0px 0px 1px green)
drop-shadow(0px 0px 1px green)
drop-shadow(0px 0px 1px green)
drop-shadow(0px 0px 1px green);
}
.box::before {
content: "";
position: absolute;
top: 100%;
left: 20%;
height: 30px;
width: 50px;
background: inherit;
clip-path: polygon(0 0, 100% 0, 50% 100%);
}
.box:hover {
background:blue;
}
body {
background:linear-gradient(to right, pink,grey);
}
<div class="box"></div>
We can extend this basic example to consider any kind of position and triangle shape:
.box {
margin: 30px;
width: 150px;
height: 80px;
display:inline-block;
border-radius: 15px;
background: red;
position: relative;
filter: /* the more shadow you add the thicker the border will be */
drop-shadow(0px 0px 1px green)
drop-shadow(0px 0px 1px green)
drop-shadow(0px 0px 1px green)
drop-shadow(0px 0px 1px green)
drop-shadow(0px 0px 1px green)
drop-shadow(0px 0px 1px green);
}
.box::before {
content: "";
position: absolute;
height: var(--h,20px);
width: var(--w,30px);
background: inherit;
transform:scale(var(--x,1),var(--y,1));
}
.box.p-bottom::before{
top: 100%;
clip-path: polygon(0 0, 100% 0, 50% 100%);
}
.box.p-bottom.alt::before{
clip-path: polygon(0 0, 100% 0, 100% 100%);
}
.box.p-top::before{
bottom: 100%;
clip-path: polygon(0 100%, 100% 100%, 50% 0);
}
.box.p-top.alt::before{
clip-path: polygon(0 100%, 100% 100%, 100% 0);
}
.box.p-left::before{
right: 100%;
clip-path: polygon(100% 0, 100% 100%,0% 50%);
}
.box.p-left.alt::before{
clip-path: polygon(100% 0, 100% 100%,0% 100%);
}
.box.p-right::before{
left: 100%;
clip-path: polygon(0% 0, 0% 100%,100% 50%);
}
.box.p-right.alt::before{
clip-path: polygon(0% 0, 0% 100%,100% 100%);
}
.box.right::before{
right:var(--p,20px);
}
.box.left::before {
left:var(--p,20px);
}
.box.top::before{
top:var(--p,20px);
}
.box.bottom::before {
bottom:var(--p,20px);
}
.box:hover {
background:blue;
}
body {
background:linear-gradient(to right, pink,grey);
}
<div class="box p-bottom right"></div>
<div class="box p-bottom right alt"></div>
<div class="box p-bottom right alt" style="--x:-1"></div>
<div class="box p-top left"></div>
<div class="box p-top right" style="--p:40%"></div>
<div class="box p-top right alt" style="--p:40%"></div>
<div class="box p-left top"></div>
<div class="box p-left top alt"></div>
<div class="box p-right bottom" style="--w:20px;"></div>
<div class="box p-right bottom" style="--p:30px;--w:20px;--h:30px"></div>
<div class="box p-right bottom alt" style="--p:30px;--w:20px;--h:30px"></div>
<div class="box p-right bottom alt" style="--p:30px;--w:20px;--h:30px;--y:-1"></div>
We can also consider any kind of background for the whole shape. The trick work for a fixed width/height. The idea is to create a background having the same size for both the main and pseudo element then we simply adjust the position of the one inside the pseudo element to match the one of the parent (to have a perfect overlap)
.box {
--h:20px;
--w:30px;
--p:20px;
margin: 30px;
width: 150px;
height: 80px;
display:inline-block;
border-radius: 15px;
background:
var(--back,linear-gradient(45deg,red,purple))
center/
calc(150px + 2*var(--w)) calc(80px + 2*var(--h));
position: relative;
filter: /* the more shadow you add the thicker the border will be */
drop-shadow(0px 0px 1px green)
drop-shadow(0px 0px 1px green)
drop-shadow(0px 0px 1px green)
drop-shadow(0px 0px 1px green)
drop-shadow(0px 0px 1px green)
drop-shadow(0px 0px 1px green);
}
.box::before {
content: "";
position: absolute;
height: var(--h);
width: var(--w);
background: inherit;
transform:scale(var(--x,1),var(--y,1));
background-position:var(--b1) 0 var(--b2);
}
.box.p-bottom::before{
top: 100%;
clip-path: polygon(0 0, 100% 0, 50% 100%);
--b1:bottom;
}
.box.p-bottom.alt::before{
clip-path: polygon(0 0, 100% 0, 100% 100%);
}
.box.p-top::before{
bottom: 100%;
clip-path: polygon(0 100%, 100% 100%, 50% 0);
--b1:top;
}
.box.p-top.alt::before{
clip-path: polygon(0 100%, 100% 100%, 100% 0);
}
.box.p-left::before{
right: 100%;
clip-path: polygon(100% 0, 100% 100%,0% 50%);
--b1:left;
}
.box.p-left.alt::before{
clip-path: polygon(100% 0, 100% 100%,0% 100%);
}
.box.p-right::before{
left: 100%;
clip-path: polygon(0% 0, 0% 100%,100% 50%);
--b1:right;
}
.box.p-right.alt::before{
clip-path: polygon(0% 0, 0% 100%,100% 100%);
}
.box.right::before{
right:var(--p);
--b2:right calc(-1*var(--p) - var(--w));
}
.box.left::before {
left:var(--p);
--b2:left calc(-1*var(--p) - var(--w));
}
.box.top::before{
top:var(--p);
--b2:top calc(-1*var(--p) - var(--h));
}
.box.bottom::before {
bottom:var(--p);
--b2:bottom calc(-1*var(--p) - var(--h));
}
body {
background:linear-gradient(to right, pink,grey);
}
<div class="box p-bottom right"></div>
<div class="box p-bottom right alt" style="--back:url(https://picsum.photos/id/15/400/300)"></div>
<div class="box p-bottom right alt" style="--x:-1;--back:red"></div>
<div class="box p-top left" style="--back:url(https://picsum.photos/id/18/400/300)"></div>
<div class="box p-top right" style="--p:40px;--back:url(https://picsum.photos/id/1018/400/300)"></div>
<div class="box p-top right alt" style="--p:60px;--back:radial-gradient(red,pink,yellow)"></div>
<div class="box p-left top" style="--back:black"></div>
<div class="box p-left top alt" style="--back:repeating-linear-gradient(45deg,#fff 0 10px,orange 0 20px)"></div>
<div class="box p-right bottom" style="--w:20px;--back:linear-gradient(red,pink,yellow)"></div>
<div class="box p-right bottom" style="--p:30px;--w:20px;--h:30px;--back:repeating-radial-gradient(#fff 0 10px,orange 0 20px)"></div>
<div class="box p-right bottom alt" style="--p:30px;--w:20px;--h:30px;--back:conic-gradient(red,pink,yellow,red)"></div>
<div class="box p-right bottom alt" style="--p:30px;--w:20px;--h:30px;--y:-1;"></div>
SVG
This does not pass a hit-test as the transparent border is also clickable
This can be done using the pointer-events in svg.
pointer-events:visibleFill; Will only select the part where there is paint.
This example uses filter_box-shadow and is not supported by IE.
Also uses two shapes.
html,
body {
margin: 0;
padding: 0;
}
.bubble {
width: 150px;
height: 150px;
-webkit-filter: drop-shadow(5px 5px 0px #aaa);
filter: drop-shadow(5px 5px 0px #aaa);
}
.bubble-shape {
fill: #1e1;
}
.shape-text {
color: black;
}
<svg class="bubble" viewBox="0 0 110 110" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none">
<g class="bubble-shape" style="cursor:pointer; pointer-events:visibleFill;">
<rect x="10" y="10" width="90" height="90" rx="15" ry="15" />
<polygon points="20,94 40,94 30,105" />
</g>
</svg>
This example uses one path
Should be fully supported by IE.
html,
body {
margin: 0;
padding: 0;
}
.bubble {
width: 150px;
height: 150px;
}
.bubble-shape {
stroke-width: 15;
stroke: #ddd;
fill: #1e1;
}
.shape-text {
color: black;
}
<svg class="bubble" viewBox="-70 -10 390 370" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none">
<g style="cursor:pointer; pointer-events:visible;">
<path class="bubble-shape" d="m 0,0 250,0 c 25,0 50,20 50,50 l 0,225 c 0,25 -25,50 -50,50 l -175,0 -25,20 -20,-20 -40,0 c -25,0 -50,-25 -50,-50 l 0,-225 C -50,25 -50,0 0,0 Z" />
</g>
</svg>

Isometric 45 degree (long/diagonal) shadow on hover using CSS or clip-path

I am trying to re-create Twitch's hover effect when hovering over game art.
https://imgur.com/ukqAxha
I have tried using clip-path, but cannot get the correct shape I am looking for. I'm not even sure if clip-path is what I should be using nor if my code would be the best for re-creating this type of effect.
https://codepen.io/thomaschsu/pen/Rwwwgex
.img-full {
position: absolute;
width: 18rem;
margin: 50px;
transition: transform 0.1s ease;
max-height: 50vh;
max-width: 35vh;
}
.box {
position: relative;
top: 11vh;
left: 11vh;
height: 47vh;
width: 35vh;
background-color: #9147ff;
z-index: -1;
display: none;
clip-path: polygon(100% 0, 100% 85%, 92% 100%, 0 100%, 0 20%, 20% 0);
}
.img-full:hover {
transform: translate(5%, -2%);
}
.img-full:hover + .box {
display: block;
}
Here is an idea with border and gradient:
img {
width:150px;
margin:20px;
border:0 solid transparent;
border-image:linear-gradient(-45deg,transparent 14px,red 15px calc(100% - 15px), transparent calc(100% - 14px)) 10;
transition:0.3s all;
}
img:hover {
border-left-width:10px;
border-bottom-width:10px;
margin-top:10px;
}
<img src="https://i.imgur.com/cFeWhuf.jpg">
Same trick with padding and background:
img {
width:150px;
margin:20px;
padding:0;
background:linear-gradient(-45deg,transparent 6px,red 7px calc(100% - 7px), transparent calc(100% - 6px));
transition:0.3s all;
}
img:hover {
padding:0 0 10px 10px;
margin-top:10px;
}
<img src="https://i.imgur.com/cFeWhuf.jpg">
you can also use a shadow
.img-banner {
float:left;/* ?? for the demo */
}
.img-full {
width: 18rem;
margin: 20px;
transition: 0.1s ease;
max-height: 50vh;
max-width: 35vh;
display:block;
}
.img-full:hover {
transform: translate(5%, -2%);
box-shadow:-1px 1px #9147ff, -2px 2px #9147ff, -3px 3px #9147ff, -4px 4px #9147ff, -5px 5px #9147ff, -6px 6px #9147ff, -7px 7px #9147ff, -8px 8px #9147ff;
}
<div class="img-banner">
<img class="img-full" src="https://i.imgur.com/cFeWhuf.jpg">
</div>
<div class="img-banner">
<img class="img-full" src="https://i.imgur.com/cFeWhuf.jpg">
</div>
<div class="img-banner">
<img class="img-full" src="https://i.imgur.com/cFeWhuf.jpg">
</div>
I've been taking a look at the website and I think they are using two invisible corners that turn to visible and flipped when the image is hovered.
I've forked your codepen and did something with this idea, check out:
https://codepen.io/ograu/pen/xxxxLLX
.img-banner {
background: #9147ff;
position: relative;
max-height: 50vh;
max-width: 35vh;
width: 18rem;
margin: 50px;
}
.img-banner:hover .corner {
transform: rotate(-45deg) scaleX(1);
transition-delay: 75ms;
display: block;
}
.img-full {
width: 100%;
height: 100%;
transition: transform 0.1s ease;
display: block;
}
.img-full:hover {
transform: translate(9px, -9px);
}
.corner {
background: #9147ff;
height: .8rem;
transition: transform .1s ease;
width: .8rem;
position: absolute;
display: none;
}
.top-left {
top: -5px;
left: 2px;
}
.bottom-right {
bottom: 4px;
right: -5px;
}
1. The obvious solution (with bad performance)
You could do this with box-shadow and triangular before and after pseudo elements. The bad thing here is the performance. The good thing is that if pseudo elements OR transitions are not supported, you still get a nice result (a purple box shadow).
.imgholder {display: inline-block; position: relative; left: 0; bottom: 0; box-shadow: 0px 0px 0px 0px #9147ff;}
.imgholder img {display: block; width: 200px; height: 100px;}
.imgholder:hover {box-shadow: -6px 6px 0px 0px #9147ff; position: relative; left: 6px; bottom: 6px;}
.imgholder::after {content: ""; position: absolute; right: 0; width: 0; height: 0; border: 0px solid transparent; border-top: 0px solid #9147ff;}
.imgholder:hover::after {border: 6px solid transparent; border-top: 6px solid #9147ff;}
.imgholder::before {content: ""; position: absolute; top: 0;left: 0; width: 0; height: 0; border: 0px solid transparent; border-right: 0px solid #9147ff; margin-left: 0px;}
.imgholder:hover::before {border: 6px solid transparent; border-right: 6px solid #9147ff; margin-left: -12px;}
.imgholder, .imgholder::before, .imgholder::after {transition: all 0.1s linear;}
<br /><div class="imgholder"><img src="https://i.imgur.com/ukqAxha.gif" /></div>
2. The solution Twitch used (with good performance)
This one is really clever. It uses 'scale' and a small rotated square (45 degrees). Note that the squares have a different transform-origin and a different rotation (direction). Performance and graceful degredation are both pretty good. This seems like the optimal solution to me.
*{font-size: 14px;}
.imgholder {
background: #9147ff;
display: inline-block;
position: relative;
}
.imgholder img {
transition: all 0.1s ease;
display: block;
width: 200px;
height: 100px;
transform: translate3d(0,0,0);
}
.imgholder:hover img {
transform: translate3d(.6rem,-.6rem,0);
transition-delay: 75ms;
}
.corner_bottom_right, .corner_top_left {
left: 0;
top: 0;
width: .8rem;
height: .8rem;
transition: all 0.1s ease;
transform: rotate(-45deg) scale(0);
background: #9147ff;
position: absolute; z-index: 0;
transform-origin: 0% 0%;
}
.corner_bottom_right {
left: auto;
top: auto;
right: 0;
bottom: 0;
transform: rotate(45deg) scale(0);
transform-origin: 100% 100%;
}
.imgholder:hover .corner_bottom_right,
.imgholder:hover .corner_top_left {
transform: rotate(-45deg) scale(1);
transition-delay: 75ms;
}
.imgholder:hover .corner_bottom_right {
transform: rotate(45deg) scale(1);
}
<br /><div class="imgholder">
<div class="corner_top_left"></div>
<div class="corner_bottom_right"></div>
<img src="https://i.imgur.com/ukqAxha.gif" />
</div>
3. Minimum amount of code (with some glitches)
The previous solutions required a lot of code. This one uses a minimum amount of code and uses the box-shadow property. I like the simplicity, but note that this solution might not look smooth on a retina display. Additionally, hovering the bottom shadow glitches and the timing seems a bit off in Firefox.
img {width: 200px; height: 100px; transition: all 0.1s ease;}
img:hover {
transform: translate(8px, -8px);
box-shadow: -1px 1px #9147ff,
-2px 2px #9147ff,
-3px 3px #9147ff,
-4px 4px #9147ff,
-5px 5px #9147ff,
-6px 6px #9147ff,
-7px 7px #9147ff,
-8px 8px #9147ff;
}
<br /><img src="https://i.imgur.com/ukqAxha.gif" />
4. Using clip-path (great performance)
The question really inspired me to create a clip-path solution. I used fixed sizes to make it easier to understand. The solution requires some smart cropping, using overflow: hidden.
.imgholder {
position: relative;
display: inline-block;
width: 200px;
height: 100px;
overflow: hidden;
transition: all 0.1s ease;
bottom: 0;
}
.imgholder img {
margin-top: -8px;
margin-right: -8px;
position: relative;
display: block;
width: 200px;
height: 100px;
transition: all 0.1s ease;
border-right: 8px solid transparent;
border-top: 8px solid transparent;
}
.clippath {
margin-top: -8px;
margin-right: -8px;
position: absolute;
top: 0;
left: 0;
width: 208px;
height: 108px;
background-color: #9147ff;
clip-path: polygon(0px 108px, 200px 108px, 208px 100px, 208px 0px, 8px 0px, 0px 8px);
transition: all 0.1s ease;
}
.imgholder:hover img,
.imgholder:hover .clippath {
margin-top: 0;
}
.imgholder:hover img {
transform: translate(8px, -8px);
}
.imgholder:hover {
width: 208px;
height: 108px;
bottom: 8px;
margin-bottom: -8px;
}
<br />
<div class="imgholder">
<div class="clippath"></div>
<img src="https://i.imgur.com/ukqAxha.gif">
</div>
<br /><br />
<div class="clippath" style="position: relative;"></div>

How can I change the size and border-radius of these insets

Below is code to a hamburger menu which I got from a Github Gist. What I want to know is why is the last bar's height not changing and how can I add rounded corners on the bars? Oh, and how can I change the height between the bars? If anyone else has CSS to a single div hamburger menu with those features, let me know.
.hamburger {
display: block;
position: absolute;
top: .5em;
right: .5em;
height: 2.5em;
width: 2.5em;
border: .8em solid rgba(0,133,255,1);
box-shadow: 0 0 0 .1em rgba(255,255,255,0),
inset 0 .3em 0 0 rgba(255,255,255,1),
inset 0 1em 0 0 rgba(0,133,255,1),
inset 0 1.3em 0 0 rgba(255,255,255,1),
inset 0 2em 0 0 rgba(0,133,250,1),
inset 0 2.5em 0 0 rgba(255,255,255,1);
}
<div class="hamburger"></div>
Here's one for you. You can adjust the roundness, thickness and color as you wish.
.menu {
position: relative;
display: inline-block;
width: 30px;
height: 5px;
top: 0px;
border-radius: 5px;
background: #000;
margin: 0;
}
.menu::before {
content: "";
position: absolute;
top: 10px;
left: 0px;
width: 30px;
height: 5px;
border-radius: 5px;
background: #000;
}
.menu::after {
content: "";
position: absolute;
top: 20px;
left: 0px;
width: 30px;
height: 5px;
border-radius: 5px;
background: #000;
}
<div class="menu"></div>
I had this one originally animate to a cross. Without animation you can reduce the code.
Creating the lines with box-shadow will prevent you from rounding them.
You may use pseudo-elements instead
.hamburger-menu
{
width:30px;
height:5px;
background-color:#111;
border-radius:5px;
position:relative;
}
.hamburger-menu:after, .hamburger-menu:before
{
content: '';
width: 100%;
height:5px;
background-color:#111;
position:absolute;
border-radius:5px;
}
.hamburger-menu:after
{
top:10px;
}
.hamburger-menu:before
{
top:20px;
}
<div class="hamburger-menu"> </div>
With the box-shadow method there's no way to add a border-radius, however this is other approach (Close hover is a plus ;) )
*,
*:after,
*:before {
margin: 0;
padding: 0;
-webkit-box-sizing: inherit;
box-sizing: inherit;
-webkit-transition: all ease 0.3s;
transition: all ease 0.3s;
}
*:hover,
*:after:hover,
*:before:hover {
-webkit-transition: all ease 0.3s;
transition: all ease 0.3s;
}
.right {
background: #000;
padding: 10px;
}
.right .bar {
width: 40px;
margin: auto;
border-radius: 2px;
height: 8px;
margin-top: 5px;
display: block;
background: #fff;
}
.right:hover .container-bar {
-webkit-transform: translateX(10px);
transform: translateX(10px);
}
.right:hover .bar {
width: 40px;
margin: auto;
height: 8px;
margin-top: 5px;
display: block;
background: #fff;
}
.right:hover .bar:nth-child(1) {
-webkit-transform-origin: left top;
transform-origin: left top;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
.right:hover .bar:nth-child(2) {
opacity: 0;
}
.right:hover .bar:nth-child(3) {
-webkit-transform-origin: left bottom;
transform-origin: left bottom;
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg);
}
<div class="right triggerMenu">
<div class="container-bar">
<a href="javascript:void(0);">
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</a>
</div>
</div>

CSS3 Set Box Shadow to aslope corner

I'm coding some fancy stuff for teaching myself.
I have an aslope left corner. Now, i want to add the box shadow and it showed like the following image:
This is my code snippet:
html, body {
margin: 0px;
}
.navbar {
position:relative;
content:"";
border-left: 300em solid #454545;
border-bottom: 120px solid transparent;
z-index: 2;
box-shadow: 0px 8px 23px 4px black;
}
.under-bar {
margin-top: -40px;
background: #851e39;
height: 200px;
opacity: 0.8
}
<html>
<body>
<div class="navbar">
</div>
<div class="under-bar">
</div>
</body>
</html>
Can someone help me to set a box-shadow under the header?
You can use transform: rotate(); instead of the border tricks.
body {
margin: 0;
}
.navbar {
height: 200px;
background-color: #9d4b61;
position: relative;
overflow: hidden;
}
.navbar:before {
content: "";
position: absolute;
left: 0;
top: -50px;
width: 100%;
height: 100px;
box-shadow: 0px 8px 23px 4px #000;
transform: rotate(-1deg);
background-color: #333;
}
.menu {
position: relative;
left: 20px;
top: 20px;
color: #fff;
}
<div class="navbar">
<div class="menu">menu</div>
</div>
You can use a border-radius and transform: scale:
body {
margin: 0;
background: #9d4b61;
}
.navbar {
width: 100%;
height: 50px;
background: #5c5c5c;
border-radius: 0 0 100%/22px 0;
box-shadow: 0px 8px 23px 4px rgba(0,0,0,0.8);
transform: scale(1.1,1);
}
<div class="navbar"></div>
The border-radius: 0 0 100%/22px 0 set a radius in the bottom right corner, which is 100% wide and 22px height, giving the radius a "stretched" look.
The transform: scale(1.1,1) is stretching the entire element, to hide the box-shadow in each side.

How to inscribe the following shape with CSS inside div?

FIDDLE
HTML
<div id="DiamondCenter">
<div id="triangle-topleft"></div>
</div>
CSS
#DiamondCenter {
position:fixed;
top:2%;
left:48%;
background: #24201a;
height:40px;
width:40px;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
z-index:20 !important;
}
#triangle-topleft {
width: 0;
height: 0;
border-top: 40px solid gray;
border-right: 40px solid transparent;
}
Using SVG:
While using SVG, you could make use of path and polyline elements to draw the required shape. As indicated by Paulie_D in comments, SVG is the better choice for such complex shapes instead of CSS (though this can be achieved with CSS also).
The approach is very simple and is as follows:
One path element for the top polygon which is drawn by joining the points at coordinates (0,50), (50,0), (100,50) and (50,70).
Another path element for the bottom polygon which is drawn by joining the points at (0,50), (50,70) and (100,50).
One polyline element for the orange border which is nothing but a line connecting (0,50), (50,70) and (100,50).
svg {
height: 100px;
width: 100px;
}
path#top {
fill: gray;
}
path#bottom {
fill: black;
}
polyline#border {
stroke: orange;
stroke-width: 2;
fill: none;
}
<svg viewBox="0 0 100 100">
<path id="top" d="M0,50 L50,0 100,50 50,70z" />
<path id="bottom" d="M0,50 L50,100 100,50 50,70z" />
<polyline id="border" points="0,50 50,70 100,50" />
</svg>
Using CSS:
You can achieve the shape provided in question by using 2 pseudo-elements which are both rotated and skewed. The dimension of each pseudo-element is calculated using Pythagoras theorem.
The shape produced using this method is responsive and can adapt to changes in dimension. Hover the shape within the snippet to see how it adapts.
*,
*:after,
*:before {
box-sizing: border-box;
}
#DiamondCenter {
position: fixed;
top: 2%;
left: 48%;
background: #24201a;
height: 40px;
width: 40px;
transform: rotate(45deg);
z-index: 20 !important;
overflow: hidden;
}
#DiamondCenter:after {
position: absolute;
content: '';
bottom: 0px;
left: -1px; /* half the width of border-left */
height: calc(100% / 1.414);
width: calc(100% / 1.414);
background: black;
border-left: 2px solid orange;
transform: rotate(40deg) skewX(-20deg);
transform-origin: bottom left;
}
#DiamondCenter:before {
position: absolute;
content: '';
top: -1px; /* half the width of border-top */
right: 0px;
height: calc(100% / 1.414);
width: calc(100% / 1.414);
background: black;
border-top: 2px solid orange;
transform: rotate(-40deg) skewY(-20deg);
transform-origin: top right;
}
/* Just for demo */
#DiamondCenter{
transition: all 1s;
}
#DiamondCenter:hover{
top: 5%;
height: 80px;
width: 80px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div id="DiamondCenter"></div>
In the below snippet, I have set different background colors for the pseudo-elements to illustrate how the shape is achieved.
*,
*:after,
*:before {
box-sizing: border-box;
}
#DiamondCenter {
position: fixed;
top: 2%;
left: 48%;
background: #24201a;
height: 40px;
width: 40px;
transform: rotate(45deg);
z-index: 20 !important;
overflow: hidden;
}
#DiamondCenter:after {
position: absolute;
content: '';
bottom: 0px;
left: -1px;
height: calc(100% / 1.414);
width: calc(100% / 1.414);
background: seagreen;
border-left: 2px solid orange;
transform: rotate(40deg) skewX(-20deg);
transform-origin: bottom left;
}
#DiamondCenter:before {
position: absolute;
content: '';
top: -1px;
right: 0px;
height: calc(100% / 1.414);
width: calc(100% / 1.414);
background: skyblue;
border-top: 2px solid orange;
transform: rotate(-40deg) skewY(-20deg);
transform-origin: top right;
}
/* Just for demo */
#DiamondCenter{
transition: all 1s;
}
#DiamondCenter:hover{
top: 5%;
height: 80px;
width: 80px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div id="DiamondCenter"></div>
This is quite a complicated shape to complete in CSS, but as shown by others it is possible.
A good alternative though would be to use SVG. Its a vector graphic so it scales brilliantly for responsiveness and is very well supported (CanIUse)
<svg width="50%" height="50%" viewBox="0 0 10 10">
<path d="M5,1
L9,5
L5,9
L1,5z" fill="grey" />
<path d="M1,5
L5,6
L9,5
L5,9z" stroke="orange" stroke-width=".1" stroke-dasharray="0,0,8.23,15" />
</svg>
You can create diamond shape using this css , suppose this is div where you want above shape id should be same as css (cut-diamond)
#cut-diamond {
border-style: solid;
border-color: transparent transparent red transparent;
border-width: 0 25px 25px 25px;
height: 0;
width: 50px;
position: relative;
margin: 20px 0 50px 0;
}
#cut-diamond:after {
content: "";
position: absolute;
top: 25px;
left: -25px;
width: 0;
height: 0;
border-style: solid;
border-color: red transparent transparent transparent;
border-width: 70px 50px 0 50px;
}
JSFiddle Demo