How can I tint a background image with CSS? - css

I have a background image set up through CSS.
html {
background-image: url('../img/cello.jpg');
background-attachment: fixed;
background-size: 100%;
}
I plan on having a different background image for different pages of the website: so it's important that text is legible over it. Right now I've got a translucent black background to my #main content box in the middle like this in order to ensure legibility:
#main {
background: rgba(0, 0, 0, 0.5);
}
What I really want to do, though, is to have that kind of translucent background over the entire background image, because the black box looks a bit clunky. I've tried making a <div id=#tint> which includes the whole HTML document and giving rgba(0, 0, 0, 0.5) to #tint, but that doesn't work at all--I can either get nothing to change or I can get the entire background to become a simple grey with no background image visible at all. Is this simply not possible?

Use background-blend-mode for a simple tint
You can use the background-blend-mode css property:
.box {
width: 300px;
height: 300px;
background-size: cover;
background-image: url('https://placehold.co/300');
}
.background-tint {
background-color: rgba(200,100,0,.5);
background-blend-mode: multiply;
}
<div class="box background-tint"></div>
Place it on any element with a background image and you're good to go.
The property is well supported in modern browsers NOT including IE 11. For non supporting browsers you can use a polyfill.
Working demo
Other Options
Use filter for a complex tint
You can use the filter css property:
.box {
width: 300px; height: 300px;
background-size: cover;
background-image: url('https://placehold.co/300');
}
.background-tint {
filter: sepia(100%) saturate(200%) brightness(70%) hue-rotate(330deg);
}
<div class="box background-tint"></div>
Place it on any element with a background image and you're good to go.
In order to change the color change the hue-rotate value.
The property is well supported in modern browsers NOT including IE 11.
Working demo
Use a flat linear-gradient and a multiple background overlay
.background-tint {
background-image:
linear-gradient( rgba(0,0,0,.5), rgba(0,0,0,.5) ),
url('http://placehold.it/420')
}
I think this is the most widely used technique but it has the downside of being hardcoded i.e. you can't just take a class, stick it on an element and make a tint.
You could make this into a less or sass mixin, something like:
less
.background-tint(#tint-color, #image-url) {
background-image:
linear-gradient( #tint-color, #tint-color ),
url( #image-url )
}
sass
#mixin background-tint($tint_color, $image_url) {
background-image:
linear-gradient( $tint_color, $tint_color ),
url( $image_url )
}
Working demo
Use a transparent background
This method has the advantage of working on most browsers and is just a nice class you add to any element.
The downside is that if you have anything else inside of that element you will have to wrap it in a div with some kind of positioning position: relative would work best.
Example:
.box {
width: 300px; height: 300px;
background-size: cover;
background-image: url('http://placehold.it/300');
color: #facebc;
}
.background-tint { position: relative; }
.background-tint::after {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,.5);
margin: auto;
}
.u-relative { position: relative; z-index: 1; }
<div class="box background-tint">
<div class="u-relative">300 x 300</div>
</div>
Working Demo

I think you need to create an overlay element (potentially div) which has the sought translucent background. Something like:
.overlay {
z-index: 1;
height: 100%;
width: 100%;
position: fixed;
overflow: auto;
top: 0px;
left: 0px;
background: rgba(0, 0, 0, 0.7); /*can be anything, of course*/
}
And of course, a little demo: little link.

This worked great for me:
https://css-tricks.com/tinted-images-multiple-backgrounds/
.tinted-image {
background:
/* top, transparent red, faked with gradient */
linear-gradient(
rgba(255, 0, 0, 0.45),
rgba(255, 0, 0, 0.45)
),
/* bottom, image */
url(image.jpg);
}
And building on another answer, you can do this with existing colors in less like:
linear-gradient(
fade(#brand-primary, 50%),
fade(#brand-primary, 50%)
),

It would be the overlay property
https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingoverlay
But it's a draft. Don't rely on it

Try opacity:
opacity:0.4;
filter:alpha(opacity=40); /* For IE8 and earlier */

This is the simplest solution to the problem in my opinion.
.parent-div{
background-color : desired-color
}
#image-id{
opacity: dersired_value%
}
To increase readibity background-color: black and opacity percentages of range 50 to 60% seem to work nicely.

Related

Where does filter:invert(1) go in shorthand background image css

I'm coding a short css button with a small image using base:64. I'd like to invert the base:64 image without inverting the linear-gradient background color. I could be less lazy and just create an invert of the base:64 image, but I feel I can just do this quicker in CSS however I can't figure out where to place the filter:invert(1) in my css shorthand. Thoughts?
Button looks like this, I just want the icon to be inverted from black to white using filter:invert(1)
https://gyazo.com/13913ed0d5713b5c62892d5f90be7518
:host {
background:url('
data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBoZWlnaHQ9IjQ4IiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSI0OCI+PHBhdGggZD0iTTI0IDEydjZsOC04LTgtOHY2Yy04Ljg0IDAtMTYgNy4xNi0xNiAxNiAwIDMuMTQuOTIgNi4wNSAyLjQ4IDguNTJsMi45Mi0yLjkyYy0uODktMS42Ny0xLjQtMy41Ny0xLjQtNS42IDAtNi42MyA1LjM3LTEyIDEyLTEyem0xMy41MiAzLjQ4bC0yLjkyIDIuOTJjLjg5IDEuNjcgMS40IDMuNTcgMS40IDUuNiAwIDYuNjMtNS4zNyAxMi0xMiAxMnYtNmwtOCA4IDggOHYtNmM4Ljg0IDAgMTYtNy4xNiAxNi0xNiAwLTMuMTQtLjkyLTYuMDUtMi40OC04LjUyeiIvPjxwYXRoIGQ9Ik0wIDBoNDh2NDhoLTQ4eiIgZmlsbD0ibm9uZSIvPgoJCgkKCTxtZXRhZGF0YT4KCQk8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiIHhtbG5zOnJkZnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDEvcmRmLXNjaGVtYSMiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyI+CgkJCTxyZGY6RGVzY3JpcHRpb24gYWJvdXQ9Imh0dHBzOi8vaWNvbnNjb3V0LmNvbS9sZWdhbCNsaWNlbnNlcyIgZGM6dGl0bGU9IlVwZGF0ZSwgQXV0b3JlbmV3LCBSZWZyZXNoLCBSZWxvYWQiIGRjOmRlc2NyaXB0aW9uPSJVcGRhdGUsIEF1dG9yZW5ldywgUmVmcmVzaCwgUmVsb2FkIiBkYzpwdWJsaXNoZXI9Ikljb25zY291dCIgZGM6ZGF0ZT0iMjAxNi0xMi0xNCIgZGM6Zm9ybWF0PSJpbWFnZS9zdmcreG1sIiBkYzpsYW5ndWFnZT0iZW4iPgoJCQkJPGRjOmNyZWF0b3I+CgkJCQkJPHJkZjpCYWc+CgkJCQkJCTxyZGY6bGk+R29vZ2xlIEluYy48L3JkZjpsaT4KCQkJCQk8L3JkZjpCYWc+CgkJCQk8L2RjOmNyZWF0b3I+CgkJCTwvcmRmOkRlc2NyaXB0aW9uPgoJCTwvcmRmOlJERj4KICAgIDwvbWV0YWRhdGE+PC9zdmc+Cg==
') no-repeat center 15% / 35%, linear-gradient(rgb(32,56,71), rgb(13,135,199)) top left / cover no-repeat;
background-color: rgb(13,135,199); /* Incase Gradient Fails */
border-radius:10px;
}
Filters apply to the whole element and all its ancestors.
You can not target a single part of this element, nor can you target only one background-image.
One solution would be to place the background-image to be filtered on a pseudo-element:
.host {
background: linear-gradient(rgb(32, 56, 71), rgb(13, 135, 199)) top left / cover no-repeat;
background-color: rgb(13, 135, 199);
/* Incase Gradient Fails */
border-radius: 10px;
width: 50vw;
height: 50vw;
position: relative;
}
.host::before {
filter: invert(1);
content: "";
width: 100%;
height: 100%;
left: 0;
right: 0;
position: absolute;
background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBoZWlnaHQ9IjQ4IiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSI0OCI+PHBhdGggZD0iTTI0IDEydjZsOC04LTgtOHY2Yy04Ljg0IDAtMTYgNy4xNi0xNiAxNiAwIDMuMTQuOTIgNi4wNSAyLjQ4IDguNTJsMi45Mi0yLjkyYy0uODktMS42Ny0xLjQtMy41Ny0xLjQtNS42IDAtNi42MyA1LjM3LTEyIDEyLTEyem0xMy41MiAzLjQ4bC0yLjkyIDIuOTJjLjg5IDEuNjcgMS40IDMuNTcgMS40IDUuNiAwIDYuNjMtNS4zNyAxMi0xMiAxMnYtNmwtOCA4IDggOHYtNmM4Ljg0IDAgMTYtNy4xNiAxNi0xNiAwLTMuMTQtLjkyLTYuMDUtMi40OC04LjUyeiIvPjxwYXRoIGQ9Ik0wIDBoNDh2NDhoLTQ4eiIgZmlsbD0ibm9uZSIvPgoJCgkKCTxtZXRhZGF0YT4KCQk8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiIHhtbG5zOnJkZnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDEvcmRmLXNjaGVtYSMiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyI+CgkJCTxyZGY6RGVzY3JpcHRpb24gYWJvdXQ9Imh0dHBzOi8vaWNvbnNjb3V0LmNvbS9sZWdhbCNsaWNlbnNlcyIgZGM6dGl0bGU9IlVwZGF0ZSwgQXV0b3JlbmV3LCBSZWZyZXNoLCBSZWxvYWQiIGRjOmRlc2NyaXB0aW9uPSJVcGRhdGUsIEF1dG9yZW5ldywgUmVmcmVzaCwgUmVsb2FkIiBkYzpwdWJsaXNoZXI9Ikljb25zY291dCIgZGM6ZGF0ZT0iMjAxNi0xMi0xNCIgZGM6Zm9ybWF0PSJpbWFnZS9zdmcreG1sIiBkYzpsYW5ndWFnZT0iZW4iPgoJCQkJPGRjOmNyZWF0b3I+CgkJCQkJPHJkZjpCYWc+CgkJCQkJCTxyZGY6bGk+R29vZ2xlIEluYy48L3JkZjpsaT4KCQkJCQk8L3JkZjpCYWc+CgkJCQk8L2RjOmNyZWF0b3I+CgkJCTwvcmRmOkRlc2NyaXB0aW9uPgoJCTwvcmRmOlJERj4KICAgIDwvbWV0YWRhdGE+PC9zdmc+Cg==') no-repeat center 15% / 35%
}
.host:hover::before {
filter: none;
}
<div class="host"></div>

Only fade part of a background to white with CSS style sheet

I'm trying to use this code in a CSS stylesheet:
.layered-image {
background: linear-gradient( to right, transparent, white 40% ),
url("http://www.azlro.org/chad/images/IMG_3699-1920x1080.JPG");
}
...to fade the background image from the image itself to white from left to right. However, I want some of image (500 pixels) to not fade at all and then start fading from there. Is that possible?
This can be achieved by using the ::before selector.
The ::before selector inserts something before the content of each selected element(s), in your case, the linear-gradient 'layer'.
I'm not totally sure this is what you are after, but hopefully this will guide you to a solution for your project. You will have to play around with the opacity, width and possibly other factors to get it exactly how you want.
As the above commenter suggested, you can add values to each color inside your linear gradient to determine the amount that you want to persist, such as:
linear-gradient(to right, transparent 500px, white);
html, body {
width: 100%;
height: 100%;
}
.layered-image {
width: 100%;
height: 100%;
background: url('https://upload.wikimedia.org/wikipedia/commons/6/62/Starsinthesky.jpg') center center no-repeat;
background-size: cover;
}
.layered-image:before {
content: '';
position: absolute;
background-image: linear-gradient(to right, transparent, white);
opacity: 2.5;
height:100%;
width:100%;
}
<div class="layered-image">
</div>
Use opacity:
.layered-image {
opacity:0.8;
}
Simply adjust the gradient:
.layered-image {
height: 200px;
background: linear-gradient( to right, transparent 0,transparent 200px /*edit this value*/ ,white 60%),
url("https://lorempixel.com/1000/800/") center/cover;
}
<div class="layered-image">
</div>

CSS fading top and bottom "borders"

Take a look at this : http://jsfiddle.net/wjhnX/
I achieved it with this CSS :
background-image: radial-gradient(#CCC, #FFF), radial-gradient(#CCC, #FFF);
background-size: 2px 100%;
background-position: 0 0, 100% 0;
background-repeat: no-repeat;
Is this possible to do but the simulated borders would be top and bottom, not left and right ?
Thanks ahead !
Do you want something like this?
Demo (Some breathing space for your content, I've used margin there, just make sure that it will apply to both, :before as well as :after, so if you want to separate, declare margin separately for each, p.s - I've made colors lil lighter)
/* Using only background gradients */
.one {
width: 400px;
padding: 20px 25px;
margin: 40px auto;
}
.one:before, .one:after {
content: "";
height: 1px;
/* I've removed the vendor prefixes, if you are looking to support older browsers
then refer to older version of this answer.
*/
background: linear-gradient(to right, rgba(0,0,0,0) 0%,rgba(147,147,147,1) 50%,rgba(0,0,0,0) 100%);
display: block;
margin-bottom: 10px;
margin-top: 10px;
}
Explanation:
I've used :before and :after pseudo having content: "", so it creates a block, you can say a virtual block inside the element... and which is further set to display: block, just make sure you use block there else margins and height will have no effect.. and last but not the least am using gradients with rgba to control the alpha/opacity of the gradient which will fade on both ends
you can make it with a seperator as well.
LIVE DEMO
.seperator
{
width: 400px;
height: 2px;
margin: 30px;
background-image: radial-gradient(#CCC, #FFF), radial-gradient(#CCC, #FFF);
background-position: 0, 100%, 0, 100%;
}
.one {
width: 400px;
height: 140px;
margin: auto;
}

Adding a CSS gradient to an image--NOT a background image

This is a page that uses a carousel (I believe flexslider). The images in this carrousel are NOT background images. I need to add a gradient to the image, going from the bottom up, and from dark to zero opacity, so that I can make the text more legible. Is this possible?
http://hungersolutionsny.magadev.net
Personally I am not a big fan of adding markup just for styling. I would go for a pseudo element :before or :after
The code would look something like this:
HTML
<div class='slideshow-wrapper'>
<img src='http://www.placekitten.com/800/300'/>
<h2 class='title'>Some title</h2>
</div>
CSS
.slideshow-wrapper {
position:relative;
float: left;
}
.title {
position: absolute;
left: 0;
right: 0;
text-align: center;
z-index: 2;
}
.slideshow-wrapper:before {
content: '';
position:absolute;
top:0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(to bottom, rgba(0,0,0,0) 0%,rgba(0,0,0,1) 100%);
z-index: 1;
}
And an example: http://jsfiddle.net/VrGeM/
Overlay the image with an absolutely positioned <div> that's the same size as the slider. Give that <div> the gradient. Ensure that it's above the images but below the text on top of the images.
It's also pretty easy to create a transparent PNG to use rather than a CSS gradient, which will have the advantage of working in older versions of IE.
The way I ususally do this is via an absolutely-positioned DIV which sits on top of the images and contains the text. Then I give that an opacity like so:
background-color: rgba(0, 0, 0, 0.56);
If you want a gradient with opacity, this is a good tool which makes that easy: http://www.colorzilla.com/gradient-editor/
There are a number of ways to tackle this. Mainly targeting the background CSS property. If you're looking to target the text that is overlapping the image you could use something simple like this:
body.front #region-content #flexslider-1 ul.slides .views-field-field-banner-statement {
background-color:rgba(0, 0, 0, 0.5);
}
It doesn't apply a gradient but it does supply a black background with 50% opacity.
I usually don't use a gradient in this way... when faced with this problem in the past I have always used an inset box-shadow on a div wrapped around the image. Something like this...
<div class="img-wrap">
<img src="" />
</div>
And then in CSS apply the box-shadow to a pseudo selector...
.img-wrap {
display: block;
position: relative;
}
.img-wrap:before {
display: block;
content: '';
position: absolute;
width: 100%;
height: 100%;
-webkit-box-shadow: inset 0 -100px 80px 0px rgba(0,0,0,0.4);
}
img {
display: block;
width: 100%;
height: auto;
}
Check out this CodePen if you want to see it live... http://cdpn.io/qGwLe

Is it possible to make a "double arrow" with css3 content technique?

Im looking for a way to recreate this button with CSS only.
I know about the triangle technique and I also know how to add a border to it, but unfortunately I don't know any way to recreate this button (without adding additional wrappers or using images).
The buttons I need this style on are <input["submit"]> and ordinary <a>'s.
With one element, you could do it using gradients and skewed pseudo-elements for a link:
demo
(you could actually do it using just gradients, but then a hover action won't be triggered on hover on the arrow shape itself, but on hover on the rectangular element containing it)
HTML:
<a class='boo' href='#'>click me</a>
Relevant CSS:
.boo {
display: inline-block;
position: relative;
padding: .5em 2em;
background:
linear-gradient(60deg, dodgerblue 50%, transparent 50%) 100% 0,
linear-gradient(-60deg, transparent 50%, dodgerblue 50%) 100% 100%,
linear-gradient(-90deg, transparent 1em, dodgerblue 1em);
background-repeat: no-repeat;
background-size: 1em 50%, 1em 50%, 100% 100%;
}
.boo:before, .boo:after {
position: absolute;
right: -.2em;
width: .5em; height: 50%;
background: dodgerblue;
content: '';
}
.boo:before {
top: 0;
transform: skewX(30deg);
}
.boo:after {
bottom: 0;
transform: skewX(-30deg);
}
EDIT:
If your background is a solid color, not an image or a gradient, you could do it in a much simpler way, without using gradients (which means that this second method also has the advantage of working in IE9).
demo #2
.boo {
display: inline-block;
position: relative;
padding: .5em 2em;
background: lightblue;
}
.boo:before, .boo:after {
position: absolute;
right: -.3em;
width: .5em; height: 50%;
box-shadow: -.2em 0 0 white;
background: inherit;
content: '';
}
.boo:before {
top: 0;
transform: skewX(30deg);
}
.boo:after {
bottom: 0;
transform: skewX(-30deg);
}
You should use a background image. Create a transparent png containing the arrow.
You would need two elements, the outer would contain the background image, the inner would contain the text, and a background color which is the same as the one on the arrow. Alternatively, you could use a second background image instead of a background color, for example if your button is not just a flat color.
The trick is to align the box containing the text with the background image.
If your arrow is 20px tall, your inner box could be e.g. 16px plus 2px padding on each side (search for box model if you would like to understand this better).
The outer element can have a right-margin set to the approximate width of the arrow image.
I hope this makes sense. The general technique is called sliding doors. I suggest reading the entire article if you have the time.

Resources