Shared translucence across two elements (without overlap)? - css

I'm pretty sure this can't be done. But there are a lot of clever people out there, so here goes...
I'm creating an UI shape using two elements that overlap. Essentially a large square with a round protrusion.
I'd like these two elements to appear as one object (which is easy to do by giving them the same background color and overlap them) but I'd also like to have this element look like it has a single drop shadow.
The catch is that drop shadows are translucent and where the two elements overlap, you will get a darker spot due to both shadow elements combining.
Example:
http://jsbin.com/maboputexa/1/
Because these are two HTML elements, I'm pretty sure there's no way around this and this is just how it is. For now, I'm going to try not using translucent objects and go with a flat solid color for the shadow. But if anyone knows of any tricks to make this work in CSS3 with all the new options, please let me know!
(Note that I'm not referring to box-shadow properties as that wouldn't work with two objects as there always would have to be one object on top of the other).

More for the fun of it than with a real use:
2 divs, having shadows that do not overlap, and transparency that don't overlap
Notice the technique to avoid the shadows overlapping: z-index auto on the divs, and the shadow set on an pseudo element with z-index negative.
And the technique to avoid the transparency overlapping is a little disturbing, since it needs not only a mix-blend-mode, but also putting the divs behind the image ...
But, as I said, it's a funny result ...
Should work in Chrome, FF and Safari (this one untested)
body {
background-color: gray;
font-size: 30px;
}
.test1 {
width: 300px;
height: 200px;
position: absolute;
left: 150px;
top: 150px;
background-color: #555;
z-index: auto;
}
.test2 {
width: 300px;
height: 200px;
position: absolute;
left: 10px;
top: 0px;
border-radius: 50%;
background-color: #555;
z-index: auto;
-webkit-animation: move 5s infinite;
animation: move 5s infinite;
}
#-webkit-keyframes move {
0% {left: 0px; top: 0px;}
33% {left: 300px; top: 20px;}
66% {left: 300px; top: 220px;}
100% {left: 0px; top: 0px;}
}
#keyframes move {
0% {left: 0px; top: 0px;}
33% {left: 300px; top: 20px;}
66% {left: 300px; top: 220px;}
100% {left: 0px; top: 0px;}
}
.test1:after , .test2:after {
content: "";
position: absolute;
left: 0px;
toop: 0px;
width: 100%;
height: 100%;
box-shadow: 4px 4px 8px 2px black;
border-radius: inherit;
z-index: -1;
}
.overlay {
width: 600px;
height: 600px;
background-image: url(http://placekitten.com/1000/750);
background-size: cover;
position: absolute;
z-index: 4;
mix-blend-mode: overlay;
pointer-events: none;
}
<div class="test1">test1</div>
<div class="test2">test2</div>
<div class="overlay"></div>

if the goal is to draw a shape with shadow you may look at svg wich will be made for this.
CSS has limits and is not really meant for drawing:
For the CSS trick with html element, background and shadow , you can easily do the background in this case, but the shadow part will be average and a lost of precious time IMHO.
See: http://jsbin.com/paqayorewo/1/ or run snippet below.
.shape1 {
width: 200px;
height: 200px;
background: rgba(0,0,0,.5);
position: absolute;
top: 200px;
box-shadow:-3px 3px 2px 0px,
50px 50px 2px -48px,
-50px -50px 2px -48px}
.shape2 {
width: 200px;
height: 200px;
border-radius: 100px;
position: absolute;
top: 100px;
left: 100px;
overflow:hidden;
box-shadow:2px -3px 3px, -20px -20px 3px -24px, -40px -15px 2px -40px, 8px 3px 3px -3px}
.shape2:before,
.shape2:after {
content:'';
background: rgba(0,0,0,.5);
position:absolute;
}
.shape2:before {
height:50%;
width:100%;
}
.shape2:after {
width:50%;
height:50%;
top:50%;
right:0;
}
body {
position:relative;
}
<div class="shape1"></div>
<div class="shape2"></div>

Related

::before and ::after elements overlapping each other ruining the background transparancy

I have a simple div element that I wanna apply a background shape to it when the user hovers over it by using the ::before and ::after pseudo elements. I rotated these elements with rotateX(). How can I style it that the elements shouldn't overlap each other (or at least not ruin the background color) but it should look like a single shape?
Tried using % but didn't work.
Please help.
Thanks so much 🙏
div{
width:200px;
padding: 18px;
margin: 10px auto;
/* border: 1px solid black; */
text-align:center;
position: relative;
perspective: 100px;
z-index: 1;
}
div:hover{
color:#fff;
}
div:hover::before, div:hover::after{
content: "";
display: block;
background-color: #00000050;
width: 100%;
height: 50px;
position: absolute;
left: 0%;
z-index: -1;
}
div::before{
top:0;
transform: rotateX(-75deg);
}
div::after{
bottom:0;
transform: rotateX(75deg);
}
<div>Hello World</div>
If you make half of each pseudo element only have the color then when you rotate them the colors don't overlap.
A minor adjustment to the padding of the div was needed to get the two rotated 'halves' to meet correctly so this would have to be looked at if you ever went for a responsive rather than a fixed px unit solution.
This snippet removes the background-color from the pseudo elements, instead using a linear-gradient background-image going just half way up (or down) the pseudo element.
div {
width: 200px;
padding: 18px;
padding: 16px;
margin: 10px auto;
/* border: 1px solid black; */
text-align: center;
position: relative;
perspective: 100px;
z-index: 1;
}
div:hover {
color: #fff;
}
div:hover::before,
div:hover::after {
content: "";
display: block;
margin: 0;
padding: 0;
width: 100%;
height: 50px;
position: absolute;
left: 0%;
z-index: -1;
}
div::before {
top: 0;
transform: rotateX(-75deg);
background-image: linear-gradient(#00000050 0 50%, transparent 50% 100%);
}
div:hover::after {
bottom: 0;
transform: rotateX(75deg);
background-color: transparent;
background-image: linear-gradient(to top, #00000050 0 50%, transparent 50% 100%);
}
<div>Hello World</div>
A Haworth's answer covers using linear gradient stops to hide the color of half of each pseudo element.
Another approach you could take is to use only one of the pseudo elements with a polygon clip path to make your shape.
.container { display: flex; }
.hoverable { position: relative; margin: auto; padding: 10px 100px; }
.hoverable:hover::before {
content: "";
position: absolute;
inset: 0;
/* top: 0; left: 0; right: 0; bottom: 0; */
background-color: rgba(0, 0, 0, 0.25);
clip-path: polygon(0 0, 100% 0, 80% 50%, 100% 100%, 0 100%, 20% 50%);
}
<div class="container">
<div class="hoverable">Hello, World!</div>
</div>

CSS: How to add slanted edge to right of div with complete browser cross-compatability?

I'm looking to achieve a slanted edge on my div. The problem I'm coming across is the simple code I found to accomplish this is not cross-browser compatible. In fact, it only shows in Chrome.
Can anyone advise on how to do the following so it works in ALL browsers:
clip-path:polygon(0 0, 70% 0, 100% 100%, 0 100%);
This effect would achieve:
Here's my entire CSS code:
.my-slanted-div {
position:absolute;
bottom:0;
left:0;
width:100px;
padding:10px 10px;
background-color:#eee;
font-size:20px;
clip-path:polygon(0 0, 70% 0, 100% 100%, 0 100%);
}
Can anyone help me out?
You can also skew pseudo-element, like this:
.my-slanted-div {
position:absolute;
bottom:40px;
left:0;
width:80px;
padding:10px 10px;
background-color:red;
font-size:20px;
}
.my-slanted-div:after {
width:50px;
background:red;
position:absolute;
height:100%;
content:' ';
right:-22px;
top:0;
transform: skew(45deg);
}
<div class="my-slanted-div">
TEXT
</div>
p.s. change angle, play with values...to get desired result...
Edit: Demo in context -> https://jsfiddle.net/Lbwj40mg/2/
This should do the trick using borders.
<div id="container">
<p id="text">Hello</p>
<div id="slanted"></div>
</div>
#container {
position: relative;
height: 200px;
width: 200px;
background:url(http://placehold.it/200x200);
}
#text {
position: absolute;
bottom: 15px;
left: 10px;
z-index: 1;
margin: 0;
}
#slanted {
position: absolute;
bottom: 0;
left: 0;
height: 0;
width: 0;
border-left: 75px solid #dedede;
border-right: 50px solid transparent;
border-bottom: 50px solid #dedede;
}
jsfiddle
I've made it work one way with :before and :after pseudos, you simply need to update the widths, heights and line-height to suit the size of tab you want; the rectangle must be the same height as the :before and :after bits for a clean look.
.box {
background: red;
width: 200px;
position: relative;
height: 100px;
line-height: 100px;
text-align: center;
margin-left: 50px;
color: white;
font-size: 21px;
font-family: arial, sans-serif;
}
.box:after {
position: absolute;
right: -50px;
content: '';
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
}
.box:before {
position: absolute;
left: -50px;
content: '';
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
}
<div class="box">
Text in the box
</div>
Here's a way with transform: rotate just to add to the list. Quite annoying as you will have to play with pixels for alignment and make some entries into #media rules for different screen sizes. But it should be fairly cross browser friendly (but maybe not opera mini)
body {
background-color: #333;
}
.container {
position: absolute; /* needs a position, relative is fine. abolsute just for this example */
top: 50%; left: 50%;
transform: translate(-50%, -50%);
width: 400px;
height: 200px;
background-color: #ccc;
overflow: hidden; /* required */
}
.salutations {
position: absolute;
bottom: 0;
left: 0;
padding: 0 10px 0 15px;
background-color: #fcfcfc;
height: 50px;
line-height: 50px; /* match height to vertically center text */
font-size: 30px;
}
.salutations::before {
content: '';
position: absolute;
top: 21px; /* play with this for alignment */
right: -36px; /* play with this for alignment */
height: 40px; width: 70px; /* may need to adjust these depending on container size */
background-color: #fcfcfc;
transform: rotate(60deg); /* to adjust angle */
z-index: -1; /* puts the pseudo element ::before below .salutations */
}
<div class="container">
<div class="salutations">Hello</div>
</div>
P.S. May have to adjust a pixel or two, my eyes suck.
Browser Compatability
transform: rotate
pseudo elements (::before)
Fiddle
https://jsfiddle.net/Hastig/wy5bjxg3/
It is most likely it is an SVG scaled to always fit its text which is simple and quick way of doing it; if you must use CSS then you could always:
Set a gradient to the div from color to transparent so that it takes up most of the div and the transition of color is abrupt and not smooth like how a normal gradient looks.
create another div and using borders create a triangle to touch the other main rectangular div such as doing:
.triangle {
width: 0;
height: 0;
border-style: solid;
border-width: 200px 200px 0 0;
border-color: #fff transparent transparent transparent;
}
Using css you can generate an element that takes the shape of a triangle.
Css tricks has a post on that.
By making the .slanted class position itself relative, we can position the generated content on the right side of the slanted div using absolute positioning.
It'll take some fiddling to get the perfect result you want, but here's an example.
.slanted{
background: #007bff;
color: #fff;
position: relative;
display:inline-block;
font-size: 20px;
height: 25px;
padding: 2px 4px;
}
.slanted::after {
content: " ";
display: block;
width: 0;
height: 0;
border-style: solid;
border-width: 29px 0 0 20px;
border-color: transparent transparent transparent #007bff;
position: absolute;
top: 0;
right: -20px;
}
<div class="slanted">Hello</div>

Creating a partial box shadow on a skewed div

I'm trying to create a partial shadow on a skewed div, as close as I can get to this creative.
Right now I've been trying to do this with pseudo elements (before specifically) but I found that those elements behave strangely whenever I skew the element they are applied to. The pseudo element keeps appearing on top of my div, even though the z-index is set to -1. No matter what I do with z-index, it will stay on top of it. I want it to be behind the div it's applied to, and in front of the div below, like in the creative.
Here's my ::before code and a link to the codepen
CSS
/*! Shadows */
#test-title {
position: relative;
}
#test-title:before {
z-index: -1;
position: absolute;
content: "";
bottom: 15px;
left: 10px;
width: 50%;
top: 80%;
max-width:300px;
box-shadow: 0 15px 10px #777;
-webkit-transform: rotate(-3deg);
-moz-transform: rotate(-3deg);
-o-transform: rotate(-3deg);
-ms-transform: rotate(-3deg);
transform: rotate(-3deg);
}
http://codepen.io/kathryncrawford/pen/WwWEma
Skew the parent then unskew the child at the same degree.
* {
box-sizing: border-box
}
body {
padding: 40px 0
}
section {
width: 60vw;
clear: both;
overflow: hidden;
min-height: 100px;
margin: 0 auto;
position: relative;
background: #035076
}
section article {
width: 60%;
padding: 20px;
color: white;
margin: 0 auto
}
section:nth-child(even) {
transform: skew(-45deg) translate(5vw);
box-shadow: inset 0 0 2px 0 black;
}
section:nth-child(odd) {
transform: skew(45deg);
}
section:nth-child(even) article {
transform: skew(45deg) translate(5vw);
}
section:nth-child(odd) article {
transform: skew(-45deg);
}
section:before,
section:after {
content: '';
position: absolute;
}
section:nth-child(even):before {
width: 100%;
height: 0;
bottom: 100%;
left: 0;
z-index: 6;
opacity: 1;
transform: rotate(-10deg) translateY(-30px);
box-shadow: 0px 0px 64px 30px rgba(0, 0, 0, 0.8);
}
section:nth-child(odd):not(:first-child):before {
width: 100%;
height: 0;
bottom: 100%;
right: 0;
z-index: 6;
opacity: 1;
transform: rotate(10deg) translateY(-30px);
box-shadow: 0px 0px 64px 30px rgba(0, 0, 0, 0.8);
}
<section>
<article>What our clients say About Us</article>
</section>
<section>
<article>Read More!</article>
</section>
<section>
<article>Read More!</article>
</section>
<section>
<article>Read More!</article>
</section>
The easier approach would be to put the drop shadow at the top of each box after the first. This will solve all sorts of z-index issues, since each box sits 1 level higher than the box above it.. and it allows the shadow to sit inside the container instead of outside of it.
I've also changed your shadow styling to use a radial gradient* instead of a box shadow, as it is a bit easier to control in this situation, and is also closer to your design. I also did a bit of positioning to make it look a bit better too, and get the separate sides for skew1 and skew2
I've changed your last ruleset to this:
.test-info:before {
position: absolute;
content: "";
width: 100%;
left: 0;
top: 0;
height: 30px;
}
.test-info.skew1:before {
background: radial-gradient(ellipse farthest-side at 30% top, rgba(0,0,0,0.5) 0%, rgba(0,0,0,0) 100%);
}
.test-info.skew2:before {
background: radial-gradient(ellipse farthest-side at 70% top, rgba(0,0,0,0.5) 0%, rgba(0,0,0,0) 100%);
}
See Demo
* note: You may want to check/add additional browser support on the gradient that I put in before using it.
I have tried, it's not perfect, but, it is closer to desired look, imho:
<div id="test-title">
<h3>What our clients say about us</h3>
</div>
<div id="shadow1"></div>
So, i've added new html element(shadow), rather than using pseudo-elements... Now, i've set z-indexes and positions properly, to hide rotated shadow div behind first div, and added this css:
#shadow1 {
position:absolute;
width:50%;
height:150px;
background:black;
top:50px;
left:11%;
z-index:6;
opacity:1;
transform: rotate(-5deg);
box-shadow: 15px 56px 50px -12px rgba(0,0,0,0.80);
}
Demo: http://codepen.io/anon/pen/vGwNqY
You can play with rotation, box-shadow, position, height... but, this could be a good start (maybe). P.S. Similar logic could be applied to second div.
try to make box shadow for the second element using :before pseudo https://jsfiddle.net/0andpzsp/
.cont {
width: 1000px;
height: 500px;
}
div[class^="d"] {
width: 70%;
height: 50%;
position: relative;
margin-left: 40px;
margin-top: 50px;
}
.d0 {
background: linear-gradient(to right, #005f8a 0%,#00486c 50%,#003a59 100%);;
transform: skew(20deg)
}
.d1 {
background: linear-gradient(to right, #005f8a 0%,#00486c 50%,#003a59 100%);;
overflow: hidden;
top: -50px;
left: 20%;
transform: skewX(-20deg);
z-index: -1
}
.d1:before {
content: '';
border-radius: 30%;
position: absolute;
display: block;
width: 600px;
height: 70px;
z-index: 9999;
top: -100px;
left: -70px;
box-shadow: -50px 60px 90px 0px #000;
transform: rotate(-5deg)
}
<div class="cont">
<div class="d0"></div>
<div class="d1">
</div>
</div>

how to apply background transparency on a div (for an AJAX loading animation)?

I've been browsing for a watch as a present to someone and I came across an ajax loading I'm trying to replicate.
I got most of it working (via looking at the CSS) except, I cannot simulate the dark/transparency happening when the ajax animation is displayed. Any ideas how it could be done?
Also Any ideas on how can I make the clock "glow"? And the color inside it white?
This is the website: http://www.jomashop.com/tissot.html?gender=25&price_filter=23789. To make the animation appear, change the price.
here's the full code I'm working on:
<html>
<head>
<style>
#ajax-loader{
display: block;
border-radius: 60px;
border: 6px solid #414C5C;
height: 80px;
width: 80px;
position: fixed;
top: 30%;
left: 50%;
background-image:none!important;
background:#fff;
-moz-box-shadow: 0 0 5px #fff;
-webkit-box-shadow: 0 0 5px #FFF;
box-shadow: 0px 0px 15px #FFF;
}
#ajax-loader::before{
content: "";
position: absolute;
background-color: #414C5C;
top:6px;
left: 48%;
height: 35px;
width: 6px;
border-radius: 5px;
-webkit-transform-origin: 50% 94%;
transform-origin: 50% 94%;
-webkit-animation: ptAiguille 12s linear infinite;
animation: ptAiguille 12s linear infinite;
}
#ajax-loader::after{
content: "";
position: absolute;
background-color: #414C5C;
top:2px;
left: 48%;
height: 38px;
width: 6px;
border-radius: 5px;
-webkit-transform-origin: 50% 97%;
transform-origin: 50% 97%;
-webkit-animation: grdAiguille 2s linear infinite;
animation: grdAiguille 2s linear infinite;
}
#-webkit-keyframes grdAiguille{
0%{-webkit-transform:rotate(0deg);}
100%{-webkit-transform:rotate(360deg);}
}
#-webkit-keyframes ptAiguille{
0%{-webkit-transform:rotate(0deg);}
100%{-webkit-transform:rotate(360deg);}
}
#page-overlay {
background: none repeat scroll 0 0 black;
position: fixed;
display: block;
opacity: 0.5;
z-index: 1000001; // or, higher
left: 0;
top: 0;
height: 100%;
width: 100%;
}
</style>
<body>
<p>testest sdfdsf sfs sdfsd sdfds f sdfsdf sfsdf s sdfsdfdsfsdf sdfsdfsd</p>
<div id="ajax-loader"></div>
<div id="page-overlay"></div>
</body>
</html>
Thanks very much
Create an overlay div at the end of your HTML and try adding the following CSS to your overlay div:
background: none repeat scroll 0 0 black;
position: fixed;
display: block;
opacity: 0.5;
z-index: 1000001; // or, higher
left: 0;
top: 0;
height: 100%;
width: 100%;
This would create a shaded transparent layer preventing you from clicking the back.
UPDATE: To apply the glow effect, add an image within your overlay div (with a class, lets say loading) and apply the following CSS to the image:
img.loading
{
box-shadow: 0px 0px 5px #fff;
}
The element they are using to provide the overlay is #backgroundPopup. If you look at the element css you will see that the opacity is set to 0.7. This allows a 30% transparency on the element, and is being triggered by javascript to show/hide the div - by default it is hidden.
element.style {
opacity: 0.7;
}
#backgroundPopup {
background: none repeat scroll 0 0 #000000;
display: none;
height: 100%;
left: 0;
position: fixed;
top: 0;
width: 100%;
z-index: 999998;
}
Using the same technique you can get this fiddle - https://jsfiddle.net/j3uhnf03/1/

CSS transition - tilting test-tube containing liquid

I have a simple CSS3 transition that involves a test tube, containing liquid, being tilted 60 degrees to the right.
Of course, liquid always stays on the horizontal plane, and it's this effect I'm having trouble with. I do have it working in a fashion, but the liquid's transition is far from convincing.
The idea was to simply rotate the liquid element, which is a child of the tube element, by the same but opposite degree, so -60. So the net, visual effect is the liquid stays at rotation 0deg. The liquid element has adequate width to allow for this rotation without showing white space.
Code Pen: http://codepen.io/anon/pen/sIDtp (currently has only -moz prefixes, no -webkit)
HTML:
<div id='container'>
<div id='tube'><div></div></div>
<div id='tube_bottom'></div>
</div>
CSS
div, button { display: block; position: relative; }
#container {
width: 50px;
height: 150px;
top: 30px;
margin: 0 auto;
transition: -moz-transform 1s
}
#container.transition { moz-transform: rotate(60deg); }
#tube {
border: solid 6px red;
border-top: none;
border-bottom: none;
width: 100%;
height: 100%;
z-index: 1;
background: #fff;
overflow: hidden;
}
#tube_bottom {
width: 100%;
height: 30%;
border-radius: 50%;
position: absolute;
bottom: -15%;
border: solid 6px red;
background: blue;
}
#tube div {
position: absolute;
left: -175px;
width: 400px;
height: 85%;
top: 30%;
background: blue;
transition: -moz-transform 1s, top 1s;
}
#container.transition #tube div { moz-transform: rotate(-60deg); top: 70%; }
As you can see, I'm having to also modify the top property, which isn't ideal and tells me I'm probably not going about this the right way. It almost looks as if the liquid element is failing to rotate about its central point (which I believe is the default value for transform-origin.
Can anyone give me some tips as to how to make this transition look natural?
Different approach : How about skewing the water?
This tube is made with :
one div and 2 pseudo elements
transform skew and rotate
box-shadows
DEMO (no vendor prefixes)
HTML :
<div class="tube"></div>
CSS :
.tube {
border: solid 6px red;
border-top: none;
border-bottom:none;
width:50px;
height:180px;
position:relative;
margin:0 auto;
transition:transform 1s;
}
.tube:after, .tube:before {
content:'';
position:absolute;
width:100%;
background:blue;
}
.tube:after {
top:100%;
left:-6px;
width:100%;
padding-bottom:100%;
border: solid 6px red;
border-top: none;
border-bottom-left-radius: 50%;
border-bottom-right-radius: 50%;
box-shadow: 0px -30px 0px -6px blue, 0px -50px 0px -6px blue;
}
.tube:before {
bottom:0;
height: 100px;
width:50px;
z-index:-1;
transition:transform 1s;
}
.tube:hover {
transform: rotate(60deg);
}
.tube:hover:before {
transform: skewY(-60deg);
}
Since the width perspective of the tube increases as it turns, the effect speed of the tilting liquid should be inversely proportional, slower when it turns, and faster when it gets back...
I got a better looking effect by setting a different transition speed for turn, and turn back:
Updated Codepen
#tube div {
position: absolute;
left: -175px;
width: 400px;
height: 85%;
top: 30%;
background: blue;
transition: -webkit-transform 1s, top 0.5s;
}
#container.transition #tube div {
-webkit-transform: rotate(-60deg);
transition: -webkit-transform 1s, top 1.4s;
top: 70%;
}
Though it could still get some improvements... (Sorry, I changed it all to -webkit-)
But perhaps you should consider using animation and #keyframes, so you could set specific values on each percentage of the transition.

Resources