Is it possible to set the opacity of a background image without affecting the opacity of child elements?
Example
All links in the footer need a custom bullet (background image) and the opacity of the custom bullet should be 50%.
HTML
<div id="footer">
<ul>
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
<li>Link 4</li>
<li>Link 5</li>
</ul>
</div>
CSS
#footer ul li {
background: url(/images/arrow.png) no-repeat 0 50%;
}
What I've Tried
I tried setting the opacity of the list items to 50%, but then the opacity of the link text is also 50% - and there doesn't seem to be a way to reset the opacity of child elements:
#footer ul li {
background: url(/images/arrow.png) no-repeat 0 50%;
/* will also set the opacity of the link text */
opacity: 0.5;
}
I also tried using rgba, but that doesn't have any effect on the background image:
#footer ul li {
/* rgba doesn't apply to the background image */
background: rgba(255, 255, 255, 0.5) url(/images/arrow.png) no-repeat 0 50%;
}
You can use CSS linear-gradient() with rgba().
div {
width: 300px;
height: 200px;
background: linear-gradient(rgba(255,255,255,.5), rgba(255,255,255,.5)), url("https://i.imgur.com/xnh5x47.jpg");
}
span {
background: black;
color: white;
}
<div><span>Hello world.</span></div>
Take your image into an image editor, turn down the opacity, save it as a .png and use that instead.
This will work with every browser
div {
-khtml-opacity:.50;
-moz-opacity:.50;
-ms-filter:"alpha(opacity=50)";
filter:alpha(opacity=50);
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0.5);
opacity:.50;
}
If you don't want transparency to affect the entire container and its children, check this workaround. You must have an absolutely positioned child with a relatively positioned parent.
Check demo at http://www.impressivewebs.com/css-opacity-that-doesnt-affect-child-elements/
If you are using the image as a bullet, you might consider the :before pseudo element.
#footer ul li {
}
#footer ul li:before {
content: url(/images/arrow.png);
filter:alpha(opacity=50);
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0.5);
opacity:.50;
}
You can put the image in the div:after or div:before and set the opacity on that "virtual div"
div:after {
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/owl1.jpg);
opacity: 0.25;
}
found here
http://css-tricks.com/snippets/css/transparent-background-images/
#footer ul li {
position: relative;
opacity: 0.99;
}
#footer ul li::before {
content: "";
position: absolute;
width: 100%;
height: 100%;
z-index: -1;
background: url(/images/arrow.png) no-repeat 0 50%;
opacity: 0.5;
}
Hack with opacity .99 (less than 1) creates z-index context so you can not worry about global z-index values. (Try to remove it and see what happens in the next demo where parent wrapper has positive z-index.)
If your element already has z-index, then you don't need this hack.
Demo of this technique.
Unfortunately, at the time of writing this answer, there is no direct way to do this. You need to:
use a semi-transparent image for background (much easier).
add an extra element (like div) next to children which you want the opaque, add background to it and after making it semi-transparent, position it behind mentioned children.
Another option is CSS Tricks approach of inserting a pseudo element the exact size of the original element right behind it to fake the opaque background effect that we're looking for. Sometimes you will need to set a height for the pseudo element.
div {
width: 200px;
height: 200px;
display: block;
position: relative;
}
div::after {
content: "";
background: url(image.jpg);
opacity: 0.5;
top: 0;
left: 0;
bottom: 0;
right: 0;
position: absolute;
z-index: -1;
}
The "filter" property, needs an integer for percentage of opacity instead of double, in order to work for IE7/8.
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=50);
P.S.: I post this as an answer, since SO, needs at least 6 changed characters for an edit.
To really fine-tune things, I recommend placing the appropriate selections in browser-targeting wrappers. This was the only thing that worked for me when I could not get IE7 and IE8 to "play nicely with others" (as I am currently working for a software company who continues to support them).
/* color or background image for all browsers, of course */
#myBackground {
background-color:#666;
}
/* target chrome & safari without disrupting IE7-8 */
#media screen and (-webkit-min-device-pixel-ratio:0) {
#myBackground {
-khtml-opacity:.50;
opacity:.50;
}
}
/* target firefox without disrupting IE */
#-moz-document url-prefix() {
#myBackground {
-moz-opacity:.50;
opacity:0.5;
}
}
/* and IE last so it doesn't blow up */
#myBackground {
opacity:.50;
filter:alpha(opacity=50);
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0.5);
}
I may have redundancies in the above code -- if anyone wishes to clean it up further, feel free!
we can figure out that by not playing with opacity just by using rgba color
e.g "background-color: rgba(0,0,0, 0.5)"
Sample :
Previous Css:
.login-card {
// .... others CSS
background-color: #121e1b;
opacity: 0.5;
}
To :
.login-card {
// .... others CSS
background-color: rgba(0, 0, 0, 0.5);
}
If you have to set the opacity only to the bullet, why don't you set the alpha channel directly into the image? By the way I don't think there is a way to set the opacity to a background image via css without changing the opacity of the whole element (and its children too).
Just to add to the above..you can use the alpha channel with the new color attributes eg. rgba(0,0,0,0) ok so this is black but with zero opacity so as a parent it will not affect the child. This only works on Chrome, FF, Safari and....I thin O.
convert your hex colours to RGBA
I found a pretty good and simple tutorial about this issue. I think it works great (and though it supports IE, I just tell my clients to use other browsers):
CSS background transparency without affecting child elements, through RGBa and filters
From there you can add gradient support, etc.
#footer ul li
{
position:relative;
list-style:none;
}
#footer ul li:before
{
background-image: url(imagesFolder/bg_demo.png);
background-repeat:no-repeat;
content: "";
top: 5px;
left: -10px;
bottom: 0;
right: 0;
position: absolute;
z-index: -1;
opacity: 0.5;
}
You can try this code. I think it will be worked. You can visit the demo
Related
This is a jsfiddle example file that replicates the problem: https://jsfiddle.net/Lhr0d6cw/11/
I wanted the element (when clicked) to expand for 6seconds from its original position but notice that when you click the red card (or any card), it doesn't start expanding from the originals position it used to be, but rather from the middle, I assume that its because transition of 6s to top and left is not being applied for some reason.
Only places I was able to make it work properly so far are stackoverflow editor below or by inserting a debugger in the code and doing it manually but when using my localhost or jsfiddle it doesn't transition properly.
This is the same example on stackoverflow which works as desired:
const productCards = document.querySelectorAll(".products__card");
productCards.forEach(c => {
// console.log("clicked1");
c.addEventListener("click", openCard)
});
function openCard(e) {
console.log("clicked");
console.dir(this);
let top = this.getBoundingClientRect().top;
let left = this.getBoundingClientRect().left;
// this.style.transition = "top 0.9s, left 0.9s";
this.style.top = top + "px";
this.style.left = left + "px";
this.style.position = "fixed";
console.log(`top: ${top}, left: ${left}`);
// debugger;
this.classList.add("open");
}
.products {
display: flex;
flex-wrap: wrap;
flex-direction: row;
justify-content: center;
min-width: 1000px;
max-width: 1500px;
margin-bottom: 300px;
}
.products .products__card {
display: flex;
flex-direction: column;
width: 150px;
height: 250px;
margin-bottom: 30px;
margin-right: 30px;
margin-left: 30px;
background-color: red;
transform: scale(1);
/* box-shadow: 3px 7px 55px -10px c(very-light); */
transition: width 0.9s, height 0.9s, z-index 0.9s, top 6s, left 6s;
}
.products .products__card.card-1 {
background-color: red;
}
.products .products__card.card-2 {
background-color: blue;
}
.products .products__card.card-3 {
background-color: green;
}
.products .products__card.card-4 {
background-color: yellow;
}
.products .products__card.card-5 {
background-color: pink;
}
.products .products__card.card-6 {
background-color: gray;
}
.products .products__card.open {
width: 550px;
height: 800px;
top: 50% !important;
left: 50% !important;
transform: translate(-50%, -50%) !important;
z-index: 120;
box-shadow: 0 0 1000px 1000px c(box-overlay);
}
<div class="products">
<div class="products__card card-1">
</div>
<div class="products__card card-2">
</div>
<div class="products__card card-3">
</div>
<div class="products__card card-4">
</div>
<div class="products__card card-5">
</div>
<div class="products__card card-6">
</div>
</div>
works when debugging:
The strange thing as mentioned above is that my problem in the browser using localhost is also solved when I insert debugger in the code and manually skip through the last step of adding .open class. If you have the same problem in jsfiddle or your own editor, try adding debugger; before this.classList.add("open"); and then open the console and then click the card and go over the last step manually in the console. you will notice that the card expanded from its original place as desired taking 6s to finish which means the transition was applied in this case.
My questions:
Why is transition for top and left only working in certain environments? is it a browser problem? I'm using the latest chrome. does someone know of a better way to achieve the same results?
code comments:
-obviously, 6 seconds is not what I will be using in my code, its used here just to make the transition obvious.
-In my source code, you can see that because I can't transition from position static to position fixed I had to use Javascript to add position fixed style inline to the element before the .open class is added, that way transition can take place properly when .open is added.
-I also added top and left values inline to keep the card in its original place when position: fixed style is applied because as you might know fixed position takes the element out of its flow, so top and left keep it in place.
-I added !important in css .open class because without it I can't override inline css as you might also know.
Thank you
I was able to solve my problem just now by applying a little hack. It seems that in some environments (localhost, jsfiddle) the javascript engine is adding the .open class faster than expected and the fact that it is working fine when debugging (slow process) indicated that to me. so I added a setTimeout() to the last piece of code delayed it by 20. this solved my problem and now it works fine on JSfiddle and on my computer. here is the new edited sample that works:
https://jsfiddle.net/Lhr0d6cw/14/
setTimeout(() => {
this.classList.add("open");
}, 20);
I would still like to know if there is a better way of doing this animation if someone would like to share!
I have a text on my website that scrolls horizontal through the page. I’m trying to get around 8 characters highlighted in black, while the rest is grey. But those characters are meant to vary as you scroll though, the highlighted bit should remain in place.
In case this doesn’t make any sense, if grey was an x, it should look something like this:
xxxxx xpsum dolox xxx xxxx
xxxx xxsum dolox sxx xxxx
xxx xxxum dolox six xxxx x
xx xxxxm dolox sit xxxx xx
I’m trying to get this done in jQuery, but I can’t get it to work. I also like to say that I’m not at all an expert in webdesign, so I don’t know what I’m doing. Anyway, I’ve tried two different approaches, one is to say “change colour of text when going over an underlying div”. The other approach is to change the colour of the text depending on the scrolling position, but the problem here is that it takes the scrolling position of the whole div, instead of a fixed position on the page. Both don’t work at the moment, examples are here:
jsfiddle 9p29tz2f
jsfiddle 9p29tz2f/1
If anyone has any ideas how to approach this, or needs some more clarification, please let me know. Many thanks!
Clone the text and set it as a child of the overlay box then scroll them together:
$(function(){
var $bodytext = $('#bodytext'),
$clone = $bodytext.clone();
//copy the text and append it to #black:
$clone.attr("id","clone").prependTo("#black");
//scroll #clone with #bodytext:
$bodytext.scroll(function(){
$clone.scrollLeft($bodytext.scrollLeft());
});
});
http://jsfiddle.net/9p29tz2f/2/
I've taken Teemu's solution and modified it a bit: http://jsfiddle.net/9af91wcL/2/
The important bits: The code moves a white DIV (#grey-overlay) on top of the text and makes it transparent. By adding black and white pixels, you get grey. The grey level is determined by the alpha channel (0.7 in the rgba() function).
You need to assign a height or it will look odd. I use 1.5em to make sure it doesn't overlap with the scroll bar of the #bodytext div.
Also make sure that the top/left position of both div's is the same.
In your real code, you can make the horizontal scrollbar disappear and scroll with JavaScript.
HTML
<div id="grey-overlay"></div>
<div id="bodytext">text...</div>
CSS
body {
background: #ffffff;
color: #000000;
font-family: sans-serif;
font-size: 200%;
}
#bodytext {
top: 15%;
width:200px;
height: 2em;
padding: 0;
position:absolute;
overflow-x:scroll;
overflow-y:hidden;
white-space: nowrap;
}
#grey-overlay {
background-color: rgba(255, 255, 255, 0.7);
width:40px;
height: 1.5em;
top:15%;
position:fixed;
z-index: 10;
}
You need to show the same content within #black as in #bodytext, and synchronize its position relative to #bodytext scrolling. This can be achieved by using an extra wrapper around #black. Something like this:
CSS:
#cover {
top: 15%;
height:50%;
width: 120px;
padding: 0;
position:fixed;
overflow-x: hidden;
background-color: #D8D8D8;
}
#black {
color: #000000;
width:100%;
height:100%;
top:0px;
left: 0px;
position:absolute;
white-space: nowrap;
z-index: 10;
}
#bodytext {
top: 15%;
width:100%;
height:85%;
padding: 0;
position:absolute;
overflow-x:scroll;
white-space: nowrap;
color: #D8D8D8;
}
HTML:
<div id="cover">
<div id="black"></div>
</div>
JS:
$(document).ready(function () {
var black = $('#black'),
btext = $('#bodytext');
black.text(btext.text()); // Clone the content
btext.scroll(function () {
var pos = btext.scrollLeft();
black.css('left', -pos + 'px'); // Set the position to match #bodytext
});
});
A live demo at jsFiddle.
Notice, that if you need some left margin, it has also to be "calculated in" to pos.
Following is my js fiddle in which i tried to create a light out effect like the following website bankalhabib.com, The issue is that on hover on menu my rest of screen is not getting dim which i actually want and instead only my menu is getting dim.
Kindly let me know ow can i resolve this issue so i can achieve the same effect as above mentioned site?
Thanks,
http://jsfiddle.net/49Qvm/9/
<ul>
<li>Home</li>
<li>About</li>
<li>Contact</li>
<li>Num</li>
</ul>
$('li').hover(function(){
$(this).addClass('hovered');
},function(){
$(this).removeClass('hovered');
});
I think your best bet would be to create an element for the darken effect on the screen. When you hover over the ul element it will toggle the visibility of the darkening element.
You will need to be sure that the z-index value for the ul element is higher than the element that provides the darkening effect (Remember this! When setting z-index on an element you will need to be sure to set it's position CSS property to relative, fixed, or absolute).
Here's a fiddle: http://jsfiddle.net/49Qvm/28/
Try this javascript/css that utilizes z-index to create a focused effect.
CSS
.link {
z-index: 700;
list-style-type: none;
padding: 0.5em;
background: black;
display: inline-block;
cursor: pointer;
color: white;
}
.dim {
width: 100%;
height: 100%;
z-index: -6;
display: none;
content: "";
position: absolute;
top: 0;
left: 0;
background: rgba(0,0,0,0.4);
}
body {
background-color: orange;
}
jQuery
var $dim = $('.dim');
$('.link').hover(function(){
$dim.fadeIn(200);
}, function(){
$dim.fadeOut(200);
});
HTML
<div class="dim"></div>
<ul>
<div class="link"><li>Home</li></div>
<div class="link"><li>Home</li></div>
<div class="link"><li>Home</li></div>
<div class="link"><li>Home</li></div>
</ul>
Some text here
http://jsfiddle.net/49Qvm/33/
I think maybe this is a scoping issue. Inside the context of the function, "this" refers to the function not the li element. I used to run into a lot of problems related to this. The solution for my cases were to look into using closures to ensure you are adding the class to the correct html element.
I have a DIV that I'd like to change the background color opacity on, depending on if the mouse is over it or not.
I know you can use background: rgba(54, 25, 25, .5) etc, but I want to set the colour separately. Is there any way I can JUST modify the OPACITY, and not the colour.
I could opacity: 0.3, etc, but that effects the whole DIV, and I just want to affect the background colour.
No html/css doesn't have that option built in, but since you're accessing/setting the colour in javascript you might as well add in your own function which can handle that for you.
Here's an example for you:
<script type="text/javascript">
function RGBA(red,green,blue,alpha) {
this.red = red;
this.green = green;
this.blue = blue;
this.alpha = alpha;
this.getCSS = function() {
return "rgba("+this.red+","+this.green+","+this.blue+","+this.alpha+")";
}
}
// store a copy of the color
var bgColor = new RGBA(255,0,0,0.5);
function setBgOpacity(elem, opac) {
bgColor.alpha = opac;
elem.style.backgroundColor = bgColor.getCSS();
}
</script>
Then in the HTML use the onmouseover event to change the opacity of the bgColor:
<div onmouseover="setBgOpacity(this, '0.3');"
onmousout="setBgOpacity(this, '0.5');">Put your mouse over me</div>
You can make the background part of a different div and set the opacity of THAT div, i.e.
<div id="container">
<div id="background"></div>
<div id="content">
<p>Lorum ipsum...</p>
</div>
</div>
And
#container { overflow:hidden; position:relative; }
#background {
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
background:#FF0000;
}
#background:hover { opacity:0.3; }
#content { position:relative; z-index:10; }
There a difference between the Alpha value in RGBa and Opacity. Opacity affects all child elements, Alpha does not.
You'll have to read the current colour value, then restate it as RGBa with the new Alpha value. You may need to convert the current hex colour value to a decimal triplet to do this.
If you are relying on RGBA to modify the opacity of the background color, no, there is no way to set that separately from the color itself. You will have to declare explicit RGBA values for both your normal and hover states.
No, you can't edit only the alpha of rgba. So you should use the RGB part of the RGBa.
If you want a separate background colour from the container you may want to use :before or :after.
.container {
position: relative;
&:before {
content: '';
position: absolute;
width: 100%;
height: 100%;
background-color: #000;
opacity: 1;
z-index: -1;
}
&:hover {
&:before {
opacity: 0.5;
}
}
.content {
z-index: 1;
}
}
When you hover on the .container, only the opacity of the :before is effected and not the contents.
I'm looking to do something like this but with CSS or JavaScript.
I need to highlight a certain part of an image but everything I find is how to do it in Photoshop. Can I do this with CSS or maybe JavaScript?
Am I even asking the right question?
EDIT:
Well here is a great submission but I have a follow up question:
I need this for a mobile device and portrait and landscape views as well for many devices like: iOS, iPad, Android, WebOS, Etc... So the fixed position I'm not sure will work.
Any advice?
You could use background-position with absolutely positioned divs as follows:
CSS:
.container {
position:relative;
height:455px;
width:606px;
}
.container div {
position:absolute;
background-image:url(http://www.beachphotos.cn/wp-content/uploads/2010/07/indoensianbeach.jpg);
}
.container .bg-image {
opacity:0.3;
height:455px;
width:606px;
}
.container div.highlight-region {
height:50px;
width:50px;
opacity:0;
}
.container div.highlight-region:hover {
opacity:1;
}
HTML:
<div class="container">
<div class="bg-image"></div>
<div class="highlight-region" style="top:50px;left:50px;background-position: -50px -50px;"></div>
<div class="highlight-region" style="top:150px;left:150px;background-position: -150px -150px;"></div>
</div>
Please see http://jsfiddle.net/MT4T7/ for an example
Credit to beachphotos.com for using their image.
EDIT (response to OP comment): Please also see http://jsfiddle.net/zLazD/ I turned off the hover aspect. also added some borders.
CSS changes:
.container div.highlight-region {
height:50px;
width:50px;
border: 3px solid white;
}
/* removed :hover section */
You can probably fake it, here is a sample:
http://jsfiddle.net/erick/JMBFS/3/
I covered the image with an opaque element. The color of the element is the same as the background of the image. Used z-index to put it on top.
You sure can. For example, most crop plugins provide "highlighting" as the basis of their UI. So for a complete cross-browser solution, just use an existing plugin, like Jcrop.
Of course, you might want it to be fixed, in which case you can programmatically tell the plugin which section to highlight and that the user shouldn't be able to move it, and then it will act as a highlighter, not a cropper.
These are the steps you can take to highlight a part of an image:
Access the image in JavaScript, and dynamically add another identical image immediately after it. (this could be done just in HTML, but it would change the semantics of your markup)
Position the second image over the first image
Apply a css mask on the second image so that only the "highlighted" part shows up
When the user hovers over the images' container, adjust the opacity of the first image.
I can provide more technical details on this later if need be.
What about overlaying the cropped image (with 100% opacity) on top of the whole image (with 30% opacity)?
This answer is only a proof of concept
body {
margin: 0 0 0 0;
padding: 0 0 0 0;
}
.img {
position: absolute;
top: 0;
left: 0;
}
.img-base {
opacity: 0.3;
z-index: -99;
}
.img-overlay {
opacity: 1.0;
}
.cropper{
width: 150px; /* input width and height of the box here */
height: 120px;
overflow: hidden;
position: relative;
padding: 0 0 0 0;
margin: 0 0 0 0;
left: 90px; top: 170px; /* input starting location of the box here */
}
#overlay1 {
position: absolute;
left: 0px; right: 0px;
margin-left: -90px; margin-top: -170px; /* input starting location of the box here */
}
<img src="https://images.unsplash.com/photo-1583355862089-81e9e6e50f7a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=334&q=80" class="img img-base">
<div class="cropper">
<img src="https://images.unsplash.com/photo-1583355862089-81e9e6e50f7a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=334&q=80" class="img img-overlay" id="overlay1">
</div>