Add shadow to custom shape made with border in CSS - css

Ok, so in HTML I have one div tag with a before and after pseudo elements. This is my CSS:
.divClass{
background: #41423D;
height:30px;
}
.divClass:before{
content: '';
line-height: 0;
font-size: 0;
width: 0;
height: 0;
border-width :15px 7px 15px 7px;
border-color: transparent #41423D #41423D transparent;
border-style:solid;
position: absolute;
top: 0;
left: -14px;
}
.divClass:after{
content: '';
line-height: 0;
font-size: 0;
width: 0;
height: 0;
border-width :15px 7px 15px 7px;
border-color: transparent transparent #41423D #41423D;
border-style:solid;
position: absolute;
top: 0;
right: -14px;
}
So, in design it becomes like this:
___
/ \
Now all I need is a shadow on the before and after pseudo elements which are the 2 triangles on either side of the div. The pseudo elements have 0 width and height so using box-shadow is a little tricky.
I need the shadow along the triangle. So, what can I do?

You can use unicode character : ▲ to make the triangles.
Apply a text shadow on it.
If the shape of the triangle is not what you want you can adjust it with transform: rotate(); or transform: skewX(); or both.
It's a bit tricky and not perfect but it can works :
span {
display: inline-block;
font-size: 70px;
transform: skewX(29.5deg);
color: red;
text-shadow: 2px 2px 4px gray;
}
<span>▲</span>
There are some other possibilities, all describe on a CSS Tricks post, so check it if you want :
https://css-tricks.com/triangle-with-shadow/
If think you can check filter: drop-shadow() too. In case you do not need a support for all the browsers it may works for you...
edit:
According to the css tricks post, can't you do that ?
.triangle-with-shadow {
transform: rotate(-45deg);
width: 100px;
height: 100px;
position: relative;
overflow: hidden;
box-shadow: 0 20px 10px -17px rgba(0, 0, 0, 0.5);
}
.triangle-with-shadow:after {
content: "";
position: absolute;
width: 50px;
height: 50px;
background: #999;
transform: rotate(45deg); /* Prefixes... */
top: 75px;
left: 25px;
box-shadow: -1px -1px 10px -2px rgba(0, 0, 0, 0.5);
}
<div class="triangle-with-shadow"></div>
Another possibility if you just want the shape that you describe is to use the perspective :
.shape {
background: #41423D;
width: 150px;
height: 150px;
margin: 20px auto;
transform-origin:50% 100%;
transform:perspective(100px) rotateX(30deg);
box-shadow: 2px 2px 15px #41423D;
}
<div class="shape"></div>

Related

CSS for Line Arrow

Does anyone have any pointers on how I can achieve the following 2 effects (red color) using pure CSS?
I am not asking for entire code but if anybody can guide me in proper direction, that would really be great.
Thanks in advance.
For second effect you should create for image's container two pseudo-elements :before and :after with border-radius set to desired value. Element :before you should position to left bottom side of container and the element :after you should position to right bottom side. You should also specify widths for each pseudo-element (for example: 50% and 50%, 60% and 40% etc.).
Code for the second effect:
.image {
position: relative;
width: 350px;
}
img {
display: block;
padding: 0;
margin: 0;
}
.image:before {
content: '';
display: inline-block;
background: rgba(255, 0, 0, .5);
width: 30%;
height: 120px;
position: absolute;
bottom: 0;
left: 0;
border-top-right-radius: 15px;
}
.image:after {
content: '';
display: inline-block;
background: rgba(255, 0, 0, .5);
width: 70%;
height: 120px;
position: absolute;
bottom: 0;
right: 0;
border-top-left-radius: 15px;
}
<div class="image">
<img src="http://placehold.it/350x350">
</div>
OK, here is a suggestion for the proper direction.
The lower red panel looks to me like two adjoining rectangles. You need to set the widths appropriately, and then for each rectangle round off one corner using border-radius: a b c d.
The effect looks to me like two of effect number 2. The red one, and then the same in white, possibly with a z-index to make sure that it (partly) covers the other one.
I trust you already know how to make the red translucent, either by using opacity or setting the colour using rgba.
I hope that helps.
You have to use the pseudo elements :after & :before to achieve the bulge in the otherwise straight div.
You may try something like this:
div {
height: 30px;
width: 200px;
background-color: red;
position: relative;
}
div:after {
content: '';
position: absolute;
left: 0;
right: 0;
width: 0px;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid #fff;
margin: auto;
}
div:before {
content: '';
position: absolute;
left: 0;
right: 0;
bottom: -8px;
width: 0px;
height: 0;
border-left: 12px solid transparent;
border-right: 12px solid transparent;
border-top: 10px solid red;
margin: auto;
}
<div></div>
Since you didn't provide a fiddle so use below solution as a guide. CSS will produces curved edges that you join together to produce desired results.
div.arrow-curved {
width: 120px;
height: 80px;
background: red;
position: relative;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
}
div.arrow-curved:before {
content:"";
position: absolute;
right: 100%;
top: 26px;
width: 0;
height: 0;
border-top: 13px solid transparent;
border-right: 26px solid red;
border-bottom: 13px solid transparent;
}
For more reference for CSS shapes: https://css-tricks.com/examples/ShapesOfCSS/

Offset border effect in pure css

I am trying to create an offset border effect. Can this be done with pure css.
These are buttons so will be different sizes and colours.
I use pseudo-element :after to create offset border effect.
body {
background: black;
padding: 30px;
}
div {
background: white;
height: 75px;
width: 175px;
position: relative;
}
div:after {
content: '';
background: transparent;
border: 1px solid white;
top: 7px;
right: 7px;
bottom: -7px;
left: -7px;
position: absolute;
z-index: -1;
}
<div></div>
Update
As web-tiki pointed out in comments on this answer, you can achieve the entire affect entirely with box-shadow. Take a look at their JSFiddle demo here: https://jsfiddle.net/5a0bvyup.
I'm going to leave my answer in the state I submitted it in because it does give some idea of how their implementation works (and if you look closely you'll see how their box-shadow differs from the one described below).
Note: In my answer I've made the foreground box red instead of white to demonstrate that this 'offset border' does not overlap the initial element. You'll need to change this back to white yourself.
The Left and Bottom Borders
You can achieve the left and bottom borders really easily with box-shadow. You simply need to create a solid shadow which matches the background colour, and then behind that add a second shadow which matches the foreground colour, offset by one pixel:
body {
background: black;
padding: 30px;
}
div {
background: red;
height: 72px;
width: 192px;
box-shadow: -2px 2px 0 5px black, -7px 7px 0 1px white;
}
<div></div>
The Top and Right Borders
You can then use pseudo-elements (::before and ::after) to fill in those extra borders:
body {
background: black;
padding: 30px;
}
div {
background: red;
height: 72px;
width: 192px;
box-shadow: -2px 2px 0 5px black, -7px 7px 0 1px white;
position: relative;
}
div::before {
background: white;
content: '';
position: absolute;
height: 1px;
width: 7px;
top: 6px;
right: 100%;
}
div::after {
background: white;
content: '';
position: absolute;
height: 7px;
width: 1px;
top: 100%;
right: 6px;
}
<div></div>

How to make a picture shadow with CSS3

I want to implement a picture shadow as below
I tried to use the following code, but that can't work as I want
Code snippet:
.oval {
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
width: 30px;
height: 5px;
border: none;
-webkit-border-radius: 50%;
border-radius: 50%;
color: rgba(0, 0, 0, 1);
-o-text-overflow: clip;
text-overflow: clip;
background: #1abc9c;
-webkit-box-shadow: 0 100px 4px -2px rgba(15, 13, 13, 0.53);
box-shadow: 0 100px 4px -2px rgba(15, 13, 13, 0.53);
-webkit-transform: scaleX(5);
transform: scaleX(5);
-webkit-transform-origin: 0 50% 0;
transform-origin: 0 50% 0;
}
<div class="oval"></div>
I want to put the HTML code below the picture if the CSS code works well.
Another method to achieve this would be to make use of a pseudo-element with CSS transform. In the below snippet, the :after pseudo-element is rotated in X-axis by close to 90deg (but not by equal to 90deg) to give it an oval like appearance. Then by adding a radial-gradient background and box-shadow, we can get an appearance close to the image in the picture.
One advantage of this approach is that the shadow that is produced is responsive and so it can adapt to change in container/image sizes.
.oval{
position: relative;
height: 200px;
width: 200px;
border: 8px solid red;
border-radius: 50%;
}
.oval img{
border-radius: 50%;
}
.oval:after{
position: absolute;
content: '';
height: 100%;
width: calc(100% - 40px); /* to offset for the shadow */
top: 25%;
left: 20px; /* to offset for the shadow spread */
border-radius: 50%;
backface-visibility: hidden;
transform-origin: 50% bottom;
transform: rotateX(85deg);
background: radial-gradient(ellipse at center, rgba(216,216,216, 0.5), rgba(248,248,248,0.1));
box-shadow: 0px 0px 20px 20px rgba(248,248,248,0.5);
}
/* Just for demo */
.oval#oval2{ height: 300px; width: 300px; }
div{ float: left; }
<div class="oval">
<img src='http://lorempixel.com/200/200/nature/1' />
</div>
<div class="oval" id="oval2">
<img src='http://lorempixel.com/300/300/nature/1' />
</div>
You could achieve this quite easily if you're able to wrap the <img /> element in a container tag such as a <div>. By using the :after pseudo-selector on the parent div, you can achieve a similar approach using box-shadow.
For example, assuming you have the following markup:
You may add the following CSS definitions:
.image-round {
border: 4px solid red;
border-radius: 50%;
}
.image-shadow {
display: inline-block;
position: relative;
}
.image-shadow:after {
display: block;
content: '';
position: absolute;
bottom: -30px;
height: 10px;
right: 5px;
left: 5px;
border-radius: 50%;
background: #ccc;
box-shadow: 0 0 10px 10px #ccc;
}
Of course, you can modify the left and right properties of the :after pseudo-element to achieve a better look.
jsFiddle Demo

Semi-transparent slanted background

I want to create an html element, e.g. a div, which is styled as follows:
semi-transparent background-color
rounded borders on all edges
left side of the div draws a straight line
right side of the div draws a skewed line
I'd like to create this in CSS only and wonder if this is possible. So far I came up with two different approaches which have their own drawbacks and are not fully sufficient. You can have a look at those in this fiddle:
https://jsfiddle.net/n4tecna3/
.one-side-skew-1,
.one-side-skew-2 {
font-size: 20px;
padding: 2%;
background-color: rgba(220, 50, 255, 0.6);
position: relative;
display: block;
border-radius: 4px;
z-index: 2;
color: #ffffff;
margin-top: 30px;
}
.one-side-skew-2 {
border-top-right-radius: 0px;
}
.one-side-skew-1:after {
height: 100%;
width: 20%;
position: absolute;
top: 0;
left: 85%;
display: inline-block;
content: "";
background-color: rgba(220, 50, 255, 0.6);
-moz-transform: skewX(-10deg);
-webkit-transform: skewX(-10deg);
-ms-transform: skewX(-10deg);
-o-transform: skewX(-10deg);
transform: skewX(-10deg);
z-index: -1;
border-radius: 4px;
}
.one-side-skew-2:after {
border-top: 1em solid rgba(220, 50, 255, 0.6);
border-left: 0.25em solid rgba(220, 50, 255, 0.6);
border-right: 0.25em solid transparent;
border-bottom: 1em solid transparent;
border-top-right-radius: 4px;
left: 100%;
display: inline-block;
position: absolute;
content: "";
top: 0;
}
.container {
width: 500px;
}
<div class="container">
<div class="one-side-skew-1">
<span class="inner-text">One Side Skew With Pseudo Element Skewed</span>
</div>
<div class="one-side-skew-2">
<span class="inner-text">One Side Skew With Pseudo Element Border</span>
</div>
</div>
Approach 1 .one-side-skew-1 uses a div element with round borders and a skewed, round-bordered pseudo element to create a one-side skewed element in sum. This works great as long as the background-color is solid. For semi-transparent backgrounds you will see an ugly color overlap where the element and its pseudo-element meet.
Approach 2 .one-side-skew2 uses a div element with a pseudo behind it that consists of borders only. It's somewhat hacky but gets close to my desired result. Still, the right does not look nearly as smooth as in the first approach.
Does someone else have a good solution for this problem in CSS only? Or will I have to use a fallback solution with a semi-transparent background-image to solve this?
You can use a pseudo element for all the background and hide the overflowing parts with the overflow property on the element.
This will prevent element and pseudo element background overlapping and allow semi transparent backgrounds:
div {
position: relative;
width: 250px;
font-size: 20px;
border-radius: 4px;
overflow: hidden;
color: #fff;
padding: 1% 2%;
}
div:before {
content: '';
position: absolute;
top: 0; right: 0;
width: 100%; height: 100%;
background: rgba(220, 50, 255, 0.6);
-webkit-transform-origin:100% 0;
-ms-transform-origin:100% 0;
transform-origin: 100% 0;
-webkit-transform: skewX(-10deg);
-ms-transform: skewX(-10deg);
transform: skewX(-10deg);
border-radius: 4px 4px 6px;
z-index: -1;
}
/** FOR THE DEMO **/body {background: url('http://lorempixel.com/output/people-q-g-640-480-3.jpg');background-size: cover;}
<div>content</div>

CSS box shadow conflicting with pseudo-element

Is there a way to disable the box shadow for the part where the pseudo-element arrow resides?
Current:
or without the negative z-index on the pseudo-element:
Desired result:
#element {
position: relative;
width: 100px;
height: 100px;
background-color: blue;
box-shadow: 5px 5px 5px #222;
}
#element::after {
content: "";
width: 25px;
height: 25px;
background-color: blue;
top: 40px;
left: 88px;
transform: rotate(45deg);
position: absolute;
z-index: -1;
-webkit-filter: drop-shadow(5px 5px 5px #222);
filter: drop-shadow(5px 5px 5px #222);
}
<div id="element"></div>
You can't control which parts of a box shadow or a drop shadow filter are rendered, at least not directly.
Depending on your layout, you could cheat by patching another pseudo-element over the one that you have. I swap the ::after with a ::before to obviate the need for z-index because boxes with the same stack level stack from back to front (meaning ::after stacks in front of ::before).
However if you have any content in your element, you will need to position the content and give it z-index: 1 to ensure that it will paint on top of both of your pseudo-element boxes, since ::after comes after the main content and will therefore also stack in front of the content. See the #element > p rule in the following example.
#element {
position: relative;
width: 100px;
height: 100px;
background-color: blue;
box-shadow: 5px 5px 5px #222;
}
#element::before, #element::after {
content: "";
background-color: inherit;
position: absolute;
}
#element::before {
width: 25px;
height: 25px;
top: 40px;
left: 88px;
transform: rotate(45deg);
-webkit-filter: drop-shadow(5px 5px 5px #222);
filter: drop-shadow(5px 5px 5px #222);
}
#element::after {
top: 0;
right: 0;
bottom: 0;
left: 0;
}
#element > p {
position: relative;
z-index: 1;
}
<div id="element"><p>text</p></div>

Resources