I want to invert text color based on the background of the text, like in this image: .
So I've tried the following code, but it didn't work:
#warp,
#text,
#tri {
position: absolute;
top: 0;
left: 0;
width: 150px;
height: 150px;
z-index: 1;
}
#warp {
background-color: orange;
}
#text {
text-align: center;
z-index: 3;
}
#text h1 {
margin: 0;
line-height: 150px;
mix-blend-mode: difference;
}
#tri {
background-color: black;
clip-path: polygon(0 0, 0 100%, 99.8% 150px);
-webkit-clip-path: polygon(0 0, 0 100%, 99.8% 150px);
z-index: 2;
}
<div id="warp">
<div id="text">
<h1>TEXT</h1>
</div>
<div id="tri"></div>
</div>
I found some results about background-image & inverted text, but I don't know how to do it with DIVs.
You can avoid clip-path by using linear-gradient as background and the mix-blend-mode will work perfectly:
#text {
width: 150px;
height: 150px;
z-index: 1;
}
#text {
text-align: center;
background: linear-gradient(to top right, black 50%, orange 51%);
}
#text h1 {
margin: 0;
line-height: 150px;
mix-blend-mode: difference;
color: #fff;
}
<div id="text">
<h1>TEXT</h1>
</div>
If you just add the same text to the tri layer, it works:
Edit: In order to allow selecting the text, I've added another transparent layer that wraps all the text as one unit. It does, however, makes updates more repetitive. As a solution, I've added the attached JavaScript code (which isn't necessary).
var text = "TEXT";
var textElements = document.getElementsByTagName("h1");
for (var i=0; i<textElements.length; i++) {
textElements[i].innerHTML = text;
}
#warp,
#text,
#tri,
#selectable {
position: absolute;
top: 0;
left: 0;
width: 150px;
height: 150px;
}
#warp {
background-color: orange;
}
#text {
text-align: center;
z-index: 1;
}
h1 {
margin: 0;
line-height: 150px;
mix-blend-mode: difference;
}
#tri {
background-color: black;
clip-path: polygon(0 0, 0 100%, 99.8% 150px);
-webkit-clip-path: polygon(0 0, 0 100%, 99.8% 150px);
z-index: 2;
color: blue;
text-align: center;
}
#selectable {
text-align: center;
z-index: 5;
color: transparent;
}
<div id="warp">
<div id="text">
<h1>TEXT</h1>
</div>
<div id="tri">
<h1>TEXT</h1>
</div>
<div id="selectable">
<h1>TEXT</h1>
</div>
</div>
Related
I'm trying to replicate a design using CSS, a simplified example of this is below:
The pink background should be 50% opacity, however the blue offset shadow/border should be 100% opacity.
I can do the general shapes but not in a way to achieve the desired transparency.
Here is an attempt I made:
.container {
position: relative;
margin: 0 auto;
width: 600px;
height: 200px;
}
.content-wrap {
position: relative;
z-index: 1;
filter: drop-shadow(13px 15px 0 rgb(0,255,255));
width: 60%;
height: 100%;
}
.content {
clip-path: polygon(0 0, 100% 0, 70% 100%, 0% 100%);
background: rgba(255,0,255, 0.5);
height: 200px;
}
.background {
z-index: 0;
position: absolute;
top: 20px;
left: 0;
background: black;
width: 500px;
height: 90px;
margin-top: 50px;
}
<div class="container">
<div class="content-wrap">
<!-- Blue -->
<div class="content">
<!-- Pink -->
</div>
</div>
<div class="background">
<!-- Black -->
</div>
</div>
A couple of aspects are not quite right:
The drop-shadow is visible through the pink, it should just be outside of the element.
The blue should extend to the left-hand edge.
The blue is transparent when I have not assigned it to be, it seems to be related to the child element's background being transparent.
Are there any CSS masters who can figure out a way to do this? The HTML can change if needed.
a box-shadow with skew transformation can do the job here. I am using pseudo-element for the sake of the demo but you can replace them with real elements
.box {
margin: 10px 0;
display: flex;
position: relative;
}
.box::before {
content: "";
position: absolute;
inset: 30% 0;
background: black;
}
.box::after {
content: "";
height: 200px;
width: 50%;
transform-origin: top;
transform: skew(-20deg);
background: rgb(255 0 255/80%);
box-shadow: 25px 25px 0 blue;
}
body {
margin: 0
}
<div class="box">
</div>
I have a request from my client to do somehting like this (css only):
On the background, have a color, sectionned on the bottom
On the right side, have a text block, sectionned on top and bottom
Between them, show an image
As you can see here. But the problem, is that the bottom of the image should follow the sectionned part of the 1 layer.
As far as I know, it's not possible to achieve such thing because of how the css is working, because the image can't be "behind" the 1 layer and in front of the 3d.
So far, I have my 2nd layer working well (I used the clippy website to help me).
The when I try to apply the clippath 1 layer, it also clips the 2nd (as expected by clippath)
This is the html of the last try i've done
<div class="parent">
<div style="background: green">
<div class="left-content" style="background: green">
<p class="top-titre">title</p>
</div>
<div class="center-content" style="background: green">
<div>
<img src="..." alt="">
</div>
</div>
<div class="right-content">
<div class="clip-top" style="background: yellow"></div>
<div class="d-flex flex-column content" style="background: yellow">
<p>subtitle</p>
<p>description</p>
</div>
<div class="clip-bottom" style="background: yellow"></div>
</div>
</div>
<div class="clip-bottom" style="background: #000000"></div>
</div>
and the last css
.parent {
margin: auto;
display: flex;
flex-direction: column;
width: 85%;
> .clip-bottom {
width: 100%;
height: 100px;
clip-path: polygon(100% 0, 0 0, 0 70%);
}
> div {
position: relative;
padding: 0 120px 0 95px;
width: 100%;
display: flex;
//clip-path: polygon(0 0, 100% 0, 100% 85%, 0% 100%);
.left-content {
width: 20%;
display: flex;
position: relative;
z-index: 5;
p {
color: white;
font-size: 2em;
font-weight: bold;
}
}
.center-content {
width: 25%;
position: relative;
img {
position: absolute;
bottom: 0;
left: 100%;
transform: translateX(-50%);
z-index: 20;
}
}
.right-content {
position: relative;
z-index: 10;
width: 55%;
.content {
padding: 40px 50px 60px 300px;
.field--name-field-titre {
.field__item {
font-size: 1.5em;
font-weight: bold;
}
}
.field--name-field-description {
padding: 70px 0 90px;
}
}
.clip-top, .clip-bottom {
height: 100px;
}
.clip-top {
clip-path: polygon(100% 30%, 0 100%, 100% 100%);
}
.clip-bottom {
clip-path: polygon(100% 0, 0 0, 100% 70%);
}
}
}
}
So, I've been trying to use an hamburger menu I made from 3 stacked div tags as a mask for a background with a color gradient (the red/yellow one, the blue/violet one is the main background).
The result I would like to achieve is this: result
I know I could simply use a svg file of the hamburger, but I would like to do this with the div tags I made so I can later animate them to transition in a x icon, as this whole thing is to create a sidebar.
html, body {
height: 100%;
background: linear-gradient(-45deg, #c850c0, #4158d0);
font-family: 'Poppins', sans-serif;
font-size: 20px;
}
.hamburger{
background: linear-gradient(-45deg, #faf617, #ff0000);
width: 50px;
height: 40px;
position: absolute;
top: 20px;
padding: 1px;
left: 20px;
}
.line{
width: 30px;
height: 4px;
margin: 7px;
border-radius: 2px;
display: block;
background-color: #ffffff;
}
<div class="hamburger">
<div class="line"></div>
<div class="line"></div>
<div class="line"></div>
</div>
Give them the same background and play with position to create the effect:
html {
height: 100%;
background: linear-gradient(-45deg, #c850c0, #4158d0);
}
.hamburger {
position: absolute;
top: 20px;
left: 20px;
/* add this to see that it's the same
background: linear-gradient(-45deg, #faf617, #ff0000); */
}
.line {
width: 30px;
height: 4px;
margin: 7px;
border-radius: 2px;
background: linear-gradient(-45deg, #faf617, #ff0000);
background-size:calc(100% + 2*7px) calc(100%*3 + 4*7px);
}
.line:nth-child(1) {
background-position:-7px -7px; /*7 = 7*1 + 0*4*/
}
.line:nth-child(2) {
background-position:-7px -18px; /*18 = 7*2 + 1*4*/
}
.line:nth-child(3) {
background-position:-7px -29px; /*29 = 7*3 + 2*4*/
}
<div class="hamburger">
<div class="line"></div>
<div class="line"></div>
<div class="line"></div>
</div>
Another idea where you can use mask with a pseudo element. The trick is to not set position to .line to make the pseudo element positionned relatively to the hamburger then you hide the overflow using mask:
html {
height: 100%;
background: linear-gradient(-45deg, #c850c0, #4158d0);
}
.hamburger {
position: absolute;
top: 20px;
left: 20px;
/* add this to see that it's the same
background: linear-gradient(-45deg, #faf617, #ff0000); */
}
.line {
width: 30px;
height: 4px;
margin: 7px;
border-radius: 2px;
-webkit-mask:linear-gradient(#fff,#fff);
mask:linear-gradient(#fff,#fff);
}
.line:before {
content:"";
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
background: linear-gradient(-45deg, #faf617, #ff0000);
}
<div class="hamburger">
<div class="line"></div>
<div class="line"></div>
<div class="line"></div>
</div>
I'm trying to achieve the following:
A background circle with a smaller colored circle inside of it, which must be centered
A small centered image inside of both circles
All of these items needs to be placed in a single div
I'm trying to do this with the minimum amount of code. I want to avoid duplication as much as possible. I believe that all of this can be achieved using before and after selectors, but I'm not sure how to get this done
Here's what I have so far:
CSS:
.grid-container {
display: grid;
grid: 100px / 100px;
}
.circle {
border-radius: 50%;
width: 100%;
height: 100%;
background-color: #e4e4e7;
}
.circle:before {
content: "";
border-radius: 50%;
width: 80%;
height: 80%;
top: 10%;
left: 10%;
background-color: blue;
display: block;
position: relative;
}
.image-one:before {
content: url("https://stackoverflow.com/favicon.ico");
}
.circle-01 {
grid-column: 1 / 2;
grid-row: 1 / 2;
}
HTML:
<div class="grid-container">
<div class="circle-01 circle image-one"></div>
</div>
I need a structure whereby I can easily change the color of the inner circle and/or image
Example
<div class="grid-container">
<div class="circle-01 circle image-one yellow"></div>
<div class="circle-01 circle image-two blue"></div>
<div class="circle-01 circle image-three green"></div>
</div>
You can do it with a pseudo element like this, putting the pseudo element on top of the main element and using borders and a background-image. You can even use a background color behind the image if it doesn't fill the whole pseudo element (note the no-repeat, the size and position settings for the background):
.x1 {
width: 300px;
height: 300px;
position: relative;
border-radius: 50%;
border: 10px solid #22f;
margin: 30px;
background: yellow;
}
.x1:after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 220px;
height: 220px;
border-radius: 50%;
border: 6px solid #f22;
background: #3d3 url(http://placehold.it/200x200/fa0/?text=this_is_an_image) center center no-repeat;
background-size: 100px 100px;
}
<div class="x1"></div>
Note: the orange square is an image, the green color around it is the background color, the red circle is the border of the pseudo element, the yellow area is the background color of the main element and the blue circle is the border of the main element. Each of these could as well be white or transparent.
ADDITION after additional question in comment:
You can also change the background-colors by adding seperate classes. In the following snippet I added two classes to the div, one that affects the background in the main element and one that affects the background-color of the pseudo element. In the latter case you have to make sure to use the background-color property, not background in the CSS rule - otherwise the background-image would disappear:
.x1 {
width: 300px;
height: 300px;
position: relative;
border-radius: 50%;
border: 10px solid #22f;
margin: 30px;
background: yellow;
}
.x1:after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 220px;
height: 220px;
border-radius: 50%;
border: 6px solid #f22;
background: #3d3 url(http://placehold.it/200x200/fa0/?text=this_is_an_image) center center no-repeat;
background-size: 100px 100px;
}
.aqua-outer-bg {
background: aqua;
}
.pink-inner-bg:after {
background-color: pink;
}
<div class="x1 aqua-outer-bg pink-inner-bg"></div>
Note: The original CSS rules remained unchanged, their background colors are overwritten by the additional classes.
ONE MORE ADDITION after additional question in comment from OP on September 18th:
Yes, you can also split that in two classes as I did below (.x1a and .x1b). I simply added both classes to the HTML tag and split up the CSS from x1:after into two rules, one for .x1a:after and one for .x2a:after
.x1a {
width: 300px;
height: 300px;
position: relative;
border-radius: 50%;
border: 10px solid #22f;
margin: 30px;
background: yellow;
}
.x1a:after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 220px;
height: 220px;
background: #3d3 url(http://placehold.it/200x200/fa0/?text=this_is_an_image) center center no-repeat;
background-size: 100px 100px;
}
.x1b:after {
border-radius: 50%;
border: 6px solid #f22;
}
.aqua-outer-bg {
background: aqua;
}
.pink-inner-bg:after {
background-color: pink;
}
<div class="x1a x1b aqua-outer-bg pink-inner-bg"></div>
Try running this snippet:
$(document).ready(function() {
var sourceIndex = 1;
var colorIndex = 1;
var colors = [
"rgb(0, 132, 203)",
"rgb(255, 192, 203)",
"rgb(50, 192, 103)",
"rgb(255, 165, 0)"
];
var sources = [
"https://www.linkedin.com/favicon.ico",
"https://www.google.com/favicon.ico",
"http://jsfiddle.net/favicon.ico",
"https://getbootstrap.com/favicon.ico",
"https://www.facebook.com/favicon.ico"
];
$("button").click(function() {
changeStuff($(this).hasClass("changeImage") ? sources : colors, $(this));
function changeStuff(list, selector) {
counter(list, selector);
if (list == sources) {
selector
.prev()
.prev(".outer-circle")
.find(".inner-circle")
.find("img")
.attr("src", list[sourceIndex]);
} else {
if (
selector
.prev(".outer-circle")
.find(".inner-circle")
.css("background-color") == colors[colorIndex]
) {
selector
.prev(".outer-circle")
.find(".inner-circle")
.css("background-color", "tan");
} else {
selector
.prev(".outer-circle")
.find(".inner-circle")
.css("background-color", colors[colorIndex]);
}
}
}
});
function counter(list, selector) {
if (list == sources) {
sourceIndex == list.length - 1 ? (sourceIndex = 0) : sourceIndex++;
} else {
colorIndex == list.length - 1 ? (colorIndex = 0) : colorIndex++;
}
}
});
.container {
display: flex;
align-items: center;
flex-direction: column;
}
.box {
display: flex;
}
.inner-circle {
border-radius: 50%;
width: 80%;
height: 80%;
display: flex;
align-items: center;
justify-content: center;
}
.box:first-child .inner-circle {
background-color: blue;
}
.box:nth-child(2) .inner-circle {
background-color: black;
}
.box:nth-child(3) .inner-circle {
background-color: maroon;
}
.outer-circle {
border-radius: 50%;
width: 100px;
height: 100px;
background-color: #e4e4e7;
display: flex;
justify-content: center;
align-items: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="box">
<div class="outer-circle">
<div class="inner-circle">
<img src="https://stackoverflow.com/favicon.ico" alt="">
</div>
</div>
<button class='changeColor'>Change Color</button>
<button class='changeImage'>Change Image</button>
</div>
<div class="box">
<div class="outer-circle">
<div class="inner-circle">
<img src="https://stackoverflow.com/favicon.ico" alt="">
</div>
</div>
<button class='changeColor'>Change Color</button>
<button class='changeImage'>Change Image</button>
</div>
<div class="box">
<div class="outer-circle">
<div class="inner-circle">
<img src="https://stackoverflow.com/favicon.ico" alt="">
</div>
</div>
<button class='changeColor'>Change Color</button>
<button class='changeImage'>Change Image</button>
</div>
</div>
Abracadabra
div {
border-radius: 50%
}
#a {
display: flex;
justify-content: center;
align-items: center;
height: 64px;
width: 64px;
border: 2px solid green;
}
img {
align-self: auto;
border: 2px solid blue;
border-radius: 50%;
padding:5%;
}
<div id="a">
<img src="https://rack.pub/media/janus.png" height="48">
</div>
I am trying to achieve something like this:
When I hover over an image, I would like to put on that image this dark color with some text and the icon.
I am stuck here. I found some tutorials but they didn't work out for this case.
Also, another issue -- every image has a different height. The width is always the same.
How can this effect be achieved?
You can achieve this with this simple CSS/HTML:
.image-container {
position: relative;
width: 200px;
height: 300px;
}
.image-container .after {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: none;
color: #FFF;
}
.image-container:hover .after {
display: block;
background: rgba(0, 0, 0, .6);
}
HTML
<div class="image-container">
<img src="http://lorempixel.com/300/200" />
<div class="after">This is some content</div>
</div>
Demo: http://jsfiddle.net/6Mt3Q/
UPD: Here is one nice final demo with some extra stylings.
.image-container {
position: relative;
display: inline-block;
}
.image-container img {display: block;}
.image-container .after {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: none;
color: #FFF;
}
.image-container:hover .after {
display: block;
background: rgba(0, 0, 0, .6);
}
.image-container .after .content {
position: absolute;
bottom: 0;
font-family: Arial;
text-align: center;
width: 100%;
box-sizing: border-box;
padding: 5px;
}
.image-container .after .zoom {
color: #DDD;
font-size: 48px;
position: absolute;
top: 50%;
left: 50%;
margin: -30px 0 0 -19px;
height: 50px;
width: 45px;
cursor: pointer;
}
.image-container .after .zoom:hover {
color: #FFF;
}
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css" rel="stylesheet"/>
<div class="image-container">
<img src="http://lorempixel.com/300/180" />
<div class="after">
<span class="content">This is some content. It can be long and span several lines.</span>
<span class="zoom">
<i class="fa fa-search"></i>
</span>
</div>
</div>
You could use a pseudo element for this, and have your image on a hover:
.image {
position: relative;
height: 300px;
width: 300px;
background: url(http://lorempixel.com/300/300);
}
.image:before {
content: "";
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
transition: all 0.8s;
opacity: 0;
background: url(http://lorempixel.com/300/200);
background-size: 100% 100%;
}
.image:hover:before {
opacity: 0.8;
}
<div class="image"></div>
Putting this answer here as it is the top result in Google.
If you want a quick and simple way:
filter: brightness(0.2);
*Not compatible with IE
A bit late for this, but this thread comes up in Google as a top result when searching for an overlay method.
You could simply use a background-blend-mode
.foo {
background-image: url(images/image1.png), url(images/image2.png);
background-color: violet;
background-blend-mode: screen multiply;
}
What this does is it takes the second image, and it blends it with the background colour by using the multiply blend mode, and then it blends the first image with the second image and the background colour by using the screen blend mode. There are 16 different blend modes that you could use to achieve any overlay.
multiply, screen, overlay, darken, lighten, color-dodge, color-burn, hard-light, soft-light, difference, exclusion, hue, saturation, color and luminosity.
.bg-img{
text-align: center;
padding: 130px 0px;
width: 100% !important;
background-size: cover !important;
background-repeat: no-repeat !important;
background: linear-gradient(0deg, rgba(0, 0, 0, 0.86), rgba(0, 0, 0, 0.86)), url(your-img-path);
}