How to connect transition to ::before psuedo-element on hover? - html

This question was migrated from Webmasters Stack Exchange because it can be answered on Stack Overflow.
Migrated last month.
I created a div that contains a background image and upon hovering an orange tint shows up over it. I used ::before psuedo-element to accomplish this.
However, I want the hover to be smooth so I used a transition. It doesn't work, unfortunately. I've no idea why. I thought you guys could help.
.img{
color: white;
height: 400px;
background-image: url("https://watermark.lovepik.com/photo/20211203/large/lovepik-serious-businessman-picture_501473287.jpg");
width: 100%;
background-size: cover;
background-position: top 35% right 0;
position: relative;
float: left;
transition: all 5s;
}
.img:hover::before{
content: "";
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(255, 88, 0, 0.7);
}
<div class="img"></div>
<h4>Jon Doe</h4>
<p>Web Developer</p>

You need to add transition to the ::before pseudo-element. Also, add the content property before it goes into the hover state.
.img::before {
content: "";
transition: all 5s;
}

I found the solution here:
CSS3 Transition on pseudo element (::before) does not work
The problem is that the pseudo-element doesn't exist when the container isn't being hovered
So I've added the .img::before part and moved the transition from .img to the .img:hover::before and it's working.
.img{
color: white;
height: 400px;
background-image: url("https://watermark.lovepik.com/photo/20211203/large/lovepik-serious-businessman-picture_501473287.jpg");
width: 100%;
background-size: cover;
background-position: top 35% right 0;
position: relative;
float: left;
}
.img::before{
content: "";
}
.img:hover::before{
content: "";
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(255, 88, 0, 0.7);
transition: all 5s;
}

Related

How do i keep my buttons in the same position on browser resize

I am adding two buttons to my web page. The problem is that when I resize my browser window the buttons get out of place and sometimes get on top of eachother depending on how I resize the window. I've searched and discovered that if I used position : absolute on the CSS it would solve the problem but it doens't solve in my code and I would like to know how can I avoid this problem.
The HTML that I have is this one :
html, body {
width: 100%;
height: 100%;
margin: 0px;
border: 0;
overflow: hidden; /* Disable scrollbars */
display: block; /* No floating content on sides */
}
.button-a,.button-b {
padding: 0.6em 2em;
border: none;
outline: none;
color: rgb(255, 255, 255);
background: rgb(209, 192, 192);
cursor: pointer;
position: absolute;
z-index: 0;
border-radius: 10px;
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
}
.button-a:before,.button-b:before {
content: "";
background: linear-gradient(
45deg,
#ff0000,
#ff7300,
#fffb00,
#48ff00,
#00ffd5,
#002bff,
#7a00ff,
#ff00c8,
#ff0000
);
position: absolute;
top: -2px;
left: -2px;
background-size: 400%;
z-index: -1;
filter: blur(5px);
-webkit-filter: blur(5px);
width: calc(100% + 4px);
height: calc(100% + 4px);
animation: glowing-button-color 20s linear infinite;
transition: opacity 0.3s ease-in-out;
border-radius: 10px;
}
#keyframes glowing-button-color {
0% {
background-position: 0 0;
}
50% {
background-position: 400% 0;
}
100% {
background-position: 0 0;
}
}
.button-a:after,.button-b:after {
z-index: -1;
content: "";
position: absolute;
width: 100%;
height: 100%;
background: #222;
left: 0;
top: 0;
border-radius: 10px;
}
.button-a {
top:1%;
left:94%;
width:100px;
height:40px;
position: absolute;
background: none;
}
.button-b {
top:5.9%;
left:94%;
width:100px;
height:40px;
position: absolute;
background: none;
}
<button type="button" class="button-a" id="button_a">A</button>
<button type="button" class="button-b" id="button_b">B</button>
I am new to CSS so I don't know much about it and don't know how to fix this issue.
I will asume your HTML is just a blank template with 2 buttons in it, just like you display it in your question.
First of all, remove the position: absolute from your buttons. You only want position: absolute to your pseudo-classes ( ::before ) if you really want to work with pseudo-classes. Replace position: absolute with position: relative on the button elements.
If you want to make your buttons to stay IN place ( as if they are pinned ) you just have to add to your code
.button-a {
inset: 10px 10px 0 0;
}
.button-b {
inset: 0 0 10px 10px;
}
Now, what this will do is simple. First keep in mind the inset is just as writing top: __, left: __, bottom: __ and right: __. This will tell the browser to render your buttons at a specific point relative to the parent element ( in this case your body - I assume ).
So the above code block can also be written like:
.button-a {
top: 10px;
left: 10px;
bottom: 0;
right: 0;
}
.button-b {
top: 0;
left: 0;
bottom: 10px;
right: 10px;
}
Setting, for example, a top value equal to 20px this translates to 20px bellow the top 'line' of your parent container the browser will place your element, in this case your button.
Just set a diferent inset for each button and I think you are good to go.

Pseudo element with z-index: -1 is hidden by background-color

I have a .link class with an ::after pseudo element underneath it (as a box-shadow on hover).
.bg {
background-color: aqua;
height: 100vh;
}
.link {
position: relative;
font-weight: bold;
}
.link::after {
content: '';
position: absolute;
z-index: -1;
top: 0;
right: 0;
bottom: 0;
left: 0;
box-shadow: 0 0 0 1em #888888 inset;
opacity: 0;
}
.link:hover::after {
opacity: 1;
}
<div class="bg">
<p class="link">Link</p>
</div>
However, when I add a background-colour to the encompassing div element, it covers up the box-shadow. I have tried adding
position: absolute;
z-index: -2;
to the div but that causes a resizing issue with the div, although the stacking is correct. I wonder if there's a preferred method to place a pseudo element above the bg layer but behind the original link class? Thanks!
Add z-index:0 (or any value) to the background element in order to create a stacking content and avoid the pseudo element moving behind:
.bg {
background-color: aqua;
height: 100vh;
position:relative;
z-index:0; /* added */
}
.link {
position: relative;
font-weight: bold;
}
.link::after {
content: '';
position: absolute;
z-index: -999; /*you can put any negative value now*/
top: 0;
right: 0;
bottom: 0;
left: 0;
box-shadow: 0 0 0 1em #888888 inset;
opacity: 0;
}
.link:hover::after {
opacity: 1;
}
<div class="bg">
<p class="link">Link</p>
</div>
Related: Why elements with any z-index value can never cover its child?

Open/close window effect with box-shadows

I was experimenting around with box-shadows and thought it would be possible to make a window effect (as in the example below) so that you can hide text or an image underneath that can only be seen - or "opened" - when you hover/click.
Unfortunately it doesn't work like that, because the shadow will always be below the text or image, which I didn't realize until I was done.
Is there a fix for this, or should I use another way to get the same result without box-shadows?
body {
background: #20262E;
}
.window {
display: inline-block;
height: 200px;
width: 300px;
margin: 20px;
background: #F8F8F8;
text-align: center;
line-height: 200px;
}
.window {
box-shadow: inset 0 200px #0084FF;
transition: box-shadow 1s ease-in-out;
}
.window:hover {
box-shadow: inset 0 0 #0084FF;
}
<div class="window">
box 1
</div>
*Note: I haven't been able to figure out why the transition is flickering :/
Agree that it's probably a bug with box-shadow. If you're looking for another CSS way to handle this, how about the :before or :after pseudo elements?
body {
background: #20262E;
}
.window {
display: inline-block;
height: 200px;
width: 300px;
margin: 20px;
background: #F8F8F8;
text-align: center;
line-height: 200px;
position: relative;
}
.window:after {
content: '';
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: #0084FF;
transition: bottom 1s ease-in-out;
}
.window:hover:after {
bottom: 100%;
}
<div class="window">box 1</div>

Css translate y making background-image disappear

I am having a problem with an element when I use the translate-y in active state, it makes the background-image disappear. Click the element and you will see the image disappear.
The Css:
.glyphsblock i {
display: inline-block;
position: relative;
width: 38px;
height: 38px;
background-size: contain;
background-repeat: no-repeat;
background-position: center, center;
border: 1px solid #fff;
margin: 1px;
flex-shrink: 0;
cursor: pointer;
transition: all ease 0.1s;
}
.glyphsblock i:before {
background: radial-gradient(#8ed3c8, #224945);
content: " ";
width: 100%;
height: 100%;
position: absolute;
z-index: -1;
top: 0;
left: 0;
}
.glyphsblock i:active {
transform: translateY(2px);
}
.glyph-A {
background-image: url(https://atlasdatabase.github.io/glyphs/a.png);
}
HTML Code:
<div class="glyphsblock">
<i class="glyph-A"></i>
</div>
Also a jsfiddle of the issue: https://jsfiddle.net/go0tbb53/
Refactor your CSS to remove the negative z-index, which can produce unpredictable results. This is what was causing the transform to glitch and hide the glyph icon.
I've adjusted your snippet so now the i itself has the radial gradient, and the ::before pseudo-element is laying the glyph graphic on top of it.
You can see it working below:
.glyphsblock i {
background: radial-gradient(#8ed3c8, #224945);
display: inline-block;
position: relative;
width: 38px;
height: 38px;
border: 1px solid #fff;
margin: 1px;
flex-shrink: 0;
cursor: pointer;
transition: all ease 0.1s;
}
.glyphsblock i::before {
background-size: contain;
background-repeat: no-repeat;
background-position: center, center;
content: '';
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.glyphsblock i:active {
transform: translateY(2px);
}
.glyph-A::before {
background-image: url(https://atlasdatabase.github.io/glyphs/a.png);
}
<div class="glyphsblock">
<i class="glyph-A"></i>
</div>
This may not be totally conventional, but I changed your jsfiddle to use a sized div for the background and an image for the icon itself. If you want to use multiple icons, simply make a larger wrapper div for multiple of what is currently called glyphsblock.
Also, my solution doesn't have any javascript, which is helpful :)
.bg-grad {
background: radial-gradient(#8ed3c8, #224945);
width: 38px;
height: 38px;
z-index: -1;
position: absolute;
}
.glyphsblock:active {
transform: translateY(2px);
cursor: pointer;
transition: all ease 0.1s;
}
<div class="glyphsblock">
<div class="bg-grad">
</div>
<img src="https://atlasdatabase.github.io/glyphs/a.png" height=38px width=38px/>
</div>

Overlap ::after and ::before with text in CSS

Goal: Make nice effect of hovering buttons in pure CSS, which will use ::after and ::before pseudo-elements. Look at this jsFiddle example to see, what I want to reach.
Code: Button will have some styling, also an background-color, which is turned off in this example.
.button {
display: inline-block;
position: relative;
height: 35px;
line-height: 35px;
padding: 0 15px;
/*background-color: white;*/
text-decoration: none;
color: black;
}
Problem: I want to use background-color and when I enable it, then I can't see pseudo-elements. It is like that, because these pseudo-elements have z-index: -1;, which put them behind the background. When I change z-index to 0 or 1, then text is not visible.
What I can't do: I can't add new elements inside buttons (like spans), because this is one already running website and client decided to change the behavior of buttons, so here I am. There are tons of buttons in this website, so this is the reason, why I want to find solution with pseudo-elements, because trying to find every single button and change them would be inappropriate.
If i understood you well, this is what you are looking for:
.button {
display: inline-block;
position: relative;
height: 35px;
line-height: 35px;
padding: 0 15px;
/*background-color: white;*/
text-decoration: none;
color: black;
border:1px solid;
}
a.button:before {
content: " ";
display: block;
z-index: -1;
position: absolute;
height: 0%;
top: 0;
right: 0;
left: 0;
background: #ddd;
transition: height 0.2s ease;
}
a.button:hover:before {
height:100%;
}
TEST
Consider an alternative method of doing the background colour transition thing.
As seen in this edited demo:
/* remove all references to .button::before */
.button {
background-image: linear-gradient(to bottom,
transparent, transparent 100%,
red 100%, red);
transition: background-image 0.5s ease 0s;
}
/* the "gradient" above has the practical result of being fully transparent,
but it has been carefully crafted so that the transition gives the desired result */
.button:hover {
background-image: linear-gradient(to bottom,
transparent, transparent 0%,
red 0%, red);
}
You can transition gadients, and in this case it is done stop-by-stop. The first and last stops don't change, but the middle two transition from 100% to 0%, essentially meaning that the cut-off point between transparent and red slides from the bottom to the top of the button, giving the effect you want.
You can now replace transparent with your desired background colour.
* You may need to remove the z-index:-1 from the ::after element to get the border effect back.
You can do something like,
HTML
CSS
body {
background: #FF7272;
}
.button {
display: inline-block;
position: relative;
height: 35px;
line-height: 35px;
padding: 0 15px;
text-decoration: none;
color: black;
z-index: 0;
background-color: white;
width: 50px;
}
.button::before, .button::after {
content: '';
position: absolute;
left: 0;
right: 0;
bottom: 0;
}
.button::after {
content: "TEST";
height: 50%;
width: 72px;
text-align: center;
z-index: 2;
line-height: 0.2;
border-left: 4px solid red;
border-right: 4px solid red;
border-bottom: 4px solid red;
}
.button::before {
height: 0%;
background-color: red;
transition: all 0.5s ease 0s;
z-index: 1;
}
.button:hover::before {
height: 100%;
}
Example: https://jsfiddle.net/LL0f7rwp/6/
Some values are hard coded, but hope you can get an idea out of it :)
It's because z-index: -1 and background-color: white will push your :before and :after elements beneath.
Remove z-index: -1 from :after and :before and add to hover .button:hover::before
Make the background-color: transparent while hovering. Updated fiddle.
body {
background: #FF7272;
}
.button {
display: inline-block;
position: relative;
height: 35px;
line-height: 35px;
padding: 0 15px;
background-color: white;
text-decoration: none;
color: black;
}
.button::before,
.button::after {
content: '';
position: absolute;
left: 0;
right: 0;
bottom: 0;
}
.button::after {
height: 50%;
border: 4px solid red;
border-top: 0;
}
.button::before {
height: 0%;
background-color: red;
transition: all 0.5s ease 0s;
}
.button:hover::before {
height: 100%;
z-index: -1;
}
.button:hover {
background-color: transparent;
}
TEST