Change Colour Opacity When Dont know RGB values only Alpha - css

I am attempting to change a buttons colour to 50% opacity when hovered over. This is simple enough when I know what the colour is but it will change at runtime.
Any ideas how I can do this with CSS3? I know I could do this easily with LESS but its not available to me.
.my-btn {
background-color: rgba(255,0,0,1); /* Will change at run time to anything */
}
.my-btn:hover {
background-color: rgba(?,?,?,0.5); /* I dont know what the rgb values will be */
}

Problem
Using the opacity property on the button itself would affect the text of the button; not ideal.
Solution
Apply the background color to a pseudo-element instead and layer it underneath the text with negative z-index. When needed, use the opacity property on the pseudo-element to create your transparent background.
Example
Note: Pseudo-elements cannot be applied to the <input> element as it cannot have children. This will only work with elements that can have children, such as <button> and <a>.
button {
position: relative;
background: none;
border: solid 1px #EEE;
padding: 10px;
border-radius: 5px;
overflow: hidden;
}
button:before {
content: '';
position: absolute;
top: -1px;
right: -1px;
bottom: -1px;
left: -1px;
background: red;
z-index: -1;
opacity: .5;
}
button:hover:before {
opacity: .8;
}
button:active:before {
background: orange;
}
<button>Button</button>

It's a bit tricky because using a combination of a rgb background color and opacity sounds like it will work but the opacity will apply to everything inside the element - including the text. there are a number of ways of getting around this though so use a solution that will work for your situation.
Essentially you've got to separate the background element from the rest of the button so that only the background color gets effected by the opacity change on hover.
.my-btn:hover a {
background-color: rgb(255,0,0);
opacity:.5;
}
<div class="my-btn">
<span aria-hidden="true">whatever</span>
<span class="sr-only">whatever</span>
</div>
Here's a demo

Use the opacity attribute:
.my-btn:hover {
opacity: 0;
}
.my-btn:hover {
opacity: 0;
}
<input class="my-btn" type="submit"></input>

Related

Changing transparent background-image on hover in front of background colour

I've had a search on here and can't seem to find anyone thread addressing the issue I'm having. If I've missed something though I apologise!
I'm doing work for a client who want a logo to change on hover state, with a background color to be assigned on hover at the same time. The logo is partially transparent, so the background color is intended to show through the logo.
I've got something working but I'm getting an annoying result whereby on the first mouseover, the background color appears to cover the whole image as a colored square. Subsequent hovers work as intended.
This made me wonder if the issue was a delay in the server providing the images. I tried preloading them but no luck.
I've got a prototype in Codepen, source code below! http://codepen.io/JD1990/pen/mPagaz
HTML
<div class="test">
<img src="http://dummyimage.com/318x318/ffffff/ffffff.png">
</div>
CSS
#preload-01 {
background: url(http://new-site-jd-5-5-16.new-site-fa.appspot.com/static/content/client-logo-bbc-inverse.png) no-repeat -9999px -9999px;
}
.test {
display: inline-block;
position: relative;
}
.test:after {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0,0,0,0);
background-image: url(http://new-site-jd-5-5-16.new-site- fa.appspot.com/static/content/client-logo-bbc-inverse.png);
background-image: url(http://new-site-jd-5-5-16.new-site-fa.appspot.com/static/content/client-logo-bbc.png);
}
.test:hover:after {
background-image: url(http://new-site-jd-5-5-16.new-site-fa.appspot.com/static/content/client-logo-bbc-inverse.png);
background-color: black;
}
Very grateful for any hints, I'm still quite inexperienced with CSS so thank you in advance :)
I'm not sure I got the question correctly, is this what you're going for?
If you change the url to a background image it will load the image only when it's hovered, while having it in the html will make the browser to load it immediately. An even better option would be to position those images one next to the other in photoshop and combine them into a sprite, then on hover you just change the background position to show one or the other.
body {
background-color: #BADA55;
}
.test {
position: relative;
}
.wt {
background-color: white;
}
.blk {
background: black;
display: none;
}
img {
position: absolute;
}
.test:hover img {
display: none;
}
.test:hover .blk {
display: block;
}
<div class="test">
<img class="wt" src="http://new-site-jd-5-5-16.new-site-fa.appspot.com/static/content/client-logo-bbc.png">
<img class="blk" src="http://new-site-jd-5-5-16.new-site-fa.appspot.com/static/content/client-logo-bbc-inverse.png" alt="" />
</div>
Added very quick transition to the background color and removed the original background color as it wasn't necessary.
Additionally, since the image isn't being changed I removed it from the :hover rule since it wasn't required. I think this might have been the issue.
body {
background: pink;
}
.test {
display: inline-block;
position: relative;
}
.test:before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-image: url(http://new-site-jd-5-5-16.new-site-fa.appspot.com/static/content/client-logo-bbc.png);
transition: background-color 0.1s ease;
}
.test:hover:before {
background-color: #000;
}
<div class="test">
<img src="http://dummyimage.com/318x318/ffffff/ffffff.png">
</div>

crossfading div backgrounds on :hover - possible in CSS?

Is there a way to smooth the transition during a div background change? Ideally I'd like to do this within the css, and not use any js.
In my css I have:
.examplediv {
background: url(img_img.png);
}
.examplediv:hover{
background: url(brighter_img.png);
}
It's doing what I'd like it to do (changing pictures), but if there was a way to make the two backgrounds "dissolve" into one another, I'd start frothing at the mouth with gratitude.
Note: The effect I'm going for is essentially an opacity change, so if it's easier to code a dissolve with :opacity, I'm all ears!
Tanks!~
It's definitely possible using just CSS. See this Fiddle for an example: https://jsfiddle.net/ffqdmcws/
HTML:
<div class="crossfade">
<div class="static"></div>
<div class="hover"></div>
</div>
CSS:
.crossfade {
position: relative;
width: 300px;
height: 200px;
}
.static, .hover {
position: absolute;
width: 100%;
height: 100%;
transition: opacity 1s ease;
}
.static {
background: url('http://lorempixel.com/300/200/food');
opacity: 1;
}
.hover {
background: url('http://lorempixel.com/300/200/cats');
opacity: 0;
}
.crossfade:hover > .static {
opacity: 0;
}
.crossfade:hover > .hover {
opacity: 1;
}
In this case I've got a container div using the crossfade class, and a couple of other divs inside that, using classes static and hover.
The static class contains the background to be shown initially, and the hover class contains the background to fade to on hover. The initial opacities are 1 for the static class and 0 for the hover class, so you only see the div with class static.
Then, if you hook up the hover action on the container div using .crossfade:hover, in order to set opacity: 0; for static and opacity: 1; for hover, that hides static and shows hover, when you hover over the container div.
Finally, to make the backgrounds overlap use absolute positioning of the two internal divs, so they're on top of each other at all times. Additionally, for the true crossfade effect you need the transition: opacity 1s ease; rule, which says you want the opacity to transition over a period of 1 second instead of switching instantly. Both the divs changing opacity from 1->0 and from 0->1 give you the crossfade effect of the background images.
You can do it with pseudo elements which are absolutely positioned. One is visible by default and another one on hover.
.examplediv {
height: 600px;
position: relative;
}
.examplediv:before, .examplediv:after {
content: '';
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: -1;
transition: opacity 0.5s ease-out;
}
.examplediv:before {
background: url(https://pixabay.com/static/uploads/photo/2015/07/19/17/38/flower-851725_960_720.jpg)
}
.examplediv:after {
background: url(https://pixabay.com/static/uploads/photo/2015/12/07/23/56/pink-flower-1081646_960_720.jpg);
opacity: 0;
}
.examplediv:hover:before {
opacity: 0;
}
.examplediv:hover:after {
opacity: 1;
}
<div class="examplediv">
</div>
JSFIDDLE

How to make hover effect not apply to :before pseudo selector?

I have a pretty simple link that is shown as block with a little green star in the corner.
JsFiddle
I want to make it so that when you hover over the link, the link itself goes slightly transparent, but the :before pseudo selector won't be affected.
I looked at some questions on this but for some reason I could not get their solutions to work. Is this possible? I am uncertain if I am simply writing the wrong CSS selectors.
EDIT: Ideally I want to be able to handle both background-images and background colors.
Use rgba(r, g, b, a) values instead.
On :hover change the alpha value.
a {
display: block;
width: 100px;
height: 100px;
background: rgba(255, 0, 0, 1);
position: relative;
}
a:before {
position: absolute;
top: 0;
left: 0;
color: white;
content: "★";
background: green;
}
a:hover {
background: rgba(255, 0, 0, 0.5);
}
If you are dealing with images, you can't actually change the opacity on an image without affect the parent. If you really want to use a pseudo selector, you can create a container around the element, attach the :before selector to that and apply the hover state only on the inner element.
div {
position: relative;
}
a {
display: block;
width: 200px;
height: 200px;
background: url(http://suptg.thisisnotatrueending.com/archive/19343530/images/1338832441002.png);
}
div:before {
position: absolute;
top:0;
left:0;
color:white;
content:"★";
background: green;
z-index: 2;
}
a:hover {
opacity: 0.5;
}
<div>
</div>
Here's an example jsFiddle

Jagged "border" showing due to background colour on wrapper element with border-radius: 50%;

As I was in the process of trying to make an animated figure (transitions on hover), I found out that the background of my <figure> is showing near the edges when I apply border-radius: 50% to it, even though my image should be taking up all available space.
For a quick demo that illustrates the problem, please look at http://codepen.io/anon/pen/KwMMKz
HTML
<figure>
<img src="http://placehold.it/400x400" alt>
<figcaption>Demo</figcaption>
</figure>
CSS
figure {
background-color: red;
width: 400px;
height: 400px;
border-radius: 50%;
overflow: hidden;
position: relative; /* For caption */
}
img {
border-radius: 50%; /* Forced on image for smooth transition */
width: 100%;
transition: opacity 1s ease-out;
}
figcaption {
position: absolute;
top: 100%;
left: 0;
width: 100%;
color: hotpink;
text-align: center;
transition: top 1s ease-out;
}
figure:hover img {
opacity: 0;
}
figure:hover figcaption {
top: 50%;
}
Please note: I know that placing the background-color on figure:hover is a work-around, but I am more interested in the reason why this "jagged border"-like look is appearing.
My guess is that it has to do with AA rendering (or something related) of the browser and that it treats the <figure> element differently than a media element such as <img>, but I can't find any proof of this online. Is this a bug, is it a "feature", or is it something I can actually fix?
Lastly, I also know that I could have used transform: translateY(); here for the animation, but that's not part of my question so please don't provide it as an answer.
UPDATE 17/12 14:03
It appears that this issue is not exclusive to border-radius: 50%. The issue can occur when any wrapping element uses border-radius in combination with overflow: hidden, when the wrapper contains content that is equal or bigger than the wrapper's dimensions.
UPDATE 17/12 14:14
Neither the usage of overflow: hidden on the wrapper element, nor the usage of border-radius on the contained image (or any other child element) seem to be the cause of this as they can be interchanged and the pixelated edge will still appear.
This seems to indicate that this issue is solely caused by 2 DOM elements being in exactly the same place, when any sort of border-radius is applied to the wrapper element and the visible area of the child is limited to that of the parent's.
I've been having same issue and ended up using pseudo element instead of background, kinda like that:
figure::before {
content: '';
display: block;
background-color: red;
width: 400px;
height: 400px;
transform: scale(0.997);
border-radius: 50%;
}
This allowed me to create 'pseudo background' which I later shrinked a little bit with transform: scale(0.997); so it will be just the same size but a bit below visible edge. Of course in your case you would also need to position image absolutely so it is not pushed below by this ::before.
It appears that it is indeed a "feature" of how the browser handles border-radius to give a smooth edge to the rounded corners of a container. The image background is anti-aliased in the same way (but as it is transparent has no effect) as can be seen by setting the img background color.
When the border is anti-aliased it "bleeds" into the background to soften the edges and so you are seeing that around the image as a "jaggy" ring in much the same way you would see a corona around the moon during a full solar eclipse.
the issue is always there, whether the anti-aliased object is covered or not, if you were to draw a circle then anti-alias it, you would see the circle is marginally narrower than the anti-aliased version. Most anti-aliasing algorithms aggregate the surrounding pixels of the object rather than those contained within it.
To overcome it, you'd either need to make your image large enough to cover the space taken up by the anti-aliased edge or reduce the container such that the anti-aliased area is smaller than the image.
You could add a new tag with an opacity of 0 then have that fade in with the image fading out.
figure {
width: 400px;
height: 400px;
border-radius: 50%;
overflow: hidden;
position: relative; /* For caption */
}
background {
background-color: red;
width: 400px;
height: 400px;
border-radius: 50%;
overflow: hidden;
opacity: 0;
position: fixed;
z-index: 5;
transition: opacity 1s ease-out;
}
img {
border-radius: 50%; /* Forced on image for smooth transition */
width: 100%;
transition: opacity 1s ease-out;
position: relative;
z-index: 100;
}
figcaption {
position: absolute;
top: 100%;
left: 0;
width: 100%;
color: hotpink;
text-align: center;
transition: top 1s ease-out;
z-index: 10000;
}
figure:hover img {
opacity: 0;
}
figure:hover background {
opacity: 1;
}
figure:hover figcaption {
top: 50%;
}
<figure>
<background></background>
<img src="http://placehold.it/400x400" alt>
<figcaption>Demo</figcaption>
</figure>
Notice I added the background tag and removed background-color from figure
http://codepen.io/marczking/pen/KwMgaR
So after playing around (used background-image and pseudo-elements, changes nothing...) you notice that this light border is only visible if you apply round corners. So I am assuming here it has to do how the Browser renders the CSS, nothing wrong with the CSS-rules ^^)
<figure>
<figcaption>Demo</figcaption>
</figure>
figure {
background-color: red;
width: 400px;
height: 400px;
border-radius: 100px;
position: relative; /* For caption */
}
figure::before {
content: "";
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
background: url("http://placehold.it/400x400") no-repeat;
border-radius: 100px; /* Forced on image for smooth transition */
transition: opacity 1s ease-out;
}
figcaption {
position: absolute;
top: 100%;
left: 0;
width: 100%;
color: hotpink;
text-align: center;
transition: top 1s ease-out;
}
figure:hover::before {
opacity: 0;
}
figure:hover figcaption {
top: 50%;
}

Change background from bottom to top on hover

How I can change the background-color on a:hover using a transition from the bottom to the top with a duration of 0.3s?
<ul>
<li><a></a></li>
<li><a></a></li>
<li><a></a></li>
</ul>
Is that possible?
Thanks
There is no way to (generically) apply a transition direction in CSS. However, we can work around that limitation by using a pseudo element (or other method like how this example uses gradients).
By using a pseudo element, which initially has a visible height of 0, we can transition the height from and to a desired direction when the link is hovered. It's best to use transform: scale for performance reasons, which means that we need to set our transform-origin to bottom center in this case to make sure it goes from bottom to top.
This approach is probably the most general, working with non-solid backgrounds and such, but does require a pseudo element or child element.
The CSS for that approach would be:
li {
background: red;
}
a {
position: relative;
z-index: 1;
}
a::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
transform: scaleY(0);
transform-origin: bottom center;
background: blue;
z-index: -1;
transition: transform 0.3s;
}
a:hover::after {
transform: scaleY(1);
}
Demo

Resources