Animating CSS gradient works only if text doesn't wrap - html

This example of animating a gradient in purely CSS works great when the text or thing doesn't wrap like text does at the end of a line. But when wrapping occurs, the gradient breaks and doesn't animate. Here is a slightly modified example to demonstrate. Shrink the screen so you can see the second block of text wrap around the edge, hover over it, and notice it won't animate.
.button {
background-size: 100%;
background-image: linear-gradient(#fff, #ccc);
border-radius: 0.45rem;
border: 1px solid #ddd;
cursor: pointer;
color: #333;
font-size: 1.25rem;
font-weight: 300;
position: relative;
}
.button:before {
border-radius: inherit;
background-image: linear-gradient(#ccc, #fff);
content: '';
display: block;
height: 100%;
position: absolute;
top: 0; left: 0;
opacity: 0;
width: 100%;
z-index: 100;
transition: opacity 0.45s;
}
.button:hover:before {
opacity: 1;
}
<span class='button'>hello</span> i am some text and then <span class='button'>i wrap around the edges</span> and go all the way around
Wondering if there is any way to get this working without using JS.

You can get a similar effect by using a gradient with larger than the display area height, and animating it's position:
.button {
background-size: 100% 150%;
background-position: 0 0;
background-image: linear-gradient(#fff 0, #ccc 50%, #fff 100%);
border-radius: 0.45rem;
border: 1px solid #ddd;
cursor: pointer;
color: #333;
font-size: 1.25rem;
font-weight: 300;
position: relative;
transition: background-position 0.45s;
}
.button:hover {
background-position: 0 100%;
}
<span class='button'>hello</span> i am some text and then <span class='button'>i wrap around the edges</span> and go all the way around

Related

CSS Opacity on Rollover Image with Text, but No Opacity Change on Text

I have an image, with text on top. When I rollover the Image I want the opacity of the background image to lower, but not the opacity for the text above it.
I thought that since the text was in a span i could simply tell the span to have the opacity: 1 !important; however that doesn't seem to do the trick. Can anyone help?
Here is the JSFiddle: https://jsfiddle.net/zerojjc/xrwao8n9/
HTML:
<div class="boxThird">
<a class="btnBox boxOne" href="<?php bloginfo('url'); ?>/" title="About Heath, Fania & Co"><span>About</span></a>
</div>
CSS:
.boxThird {
float: left;
width: 33.33%;
height: 400px;
background: #000;
}
.boxThird span {
margin-left: 25px;
position: relative;
top: 344px;
text-decoration: none;
border-bottom: 1px solid #fff;
}
.btnBox {
display: block;
text-align: left;
color: #fff;
text-shadow: 0px 0px 2px #555;
text-transform: uppercase;
text-decoration: none;
font-weight: 400;
font-size: 2em;
letter-spacing: .125em;
}
.boxOne {
height: 100%;
width: 100%;
background-position: center;
background-size: cover;
}
.boxOne {
background-image: url(https://i.imgur.com/izS0fLZ.jpg);
}
.boxOne:hover{
opacity: 0.8;
}
.boxOne:hover span{
opacity: 1 !important;
}
Opacity cascades, which means that if you have a span inside a div and they both have 0.8 opacity, the child-span would actually have 80% opacity of the parents 80% opacity (so IDK, 64% opacity). So by setting opacity: 1 to your span, you basically set it to the parents 0.8 opacity.
To prevent this, you can move the background image into a :before pseudo element and just change the :before opacity.
You can see a working example here:
https://jsfiddle.net/xr06hby2/
Relevant CSS:
.boxOne {
position: relative;
}
.boxOne:before {
content: '';
background-image: url(https://i.imgur.com/izS0fLZ.jpg);
background-position: center;
background-size: cover;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
opacity: 1;
transition: opacity 0.3s;
}
.boxOne:hover:before{
opacity: 0.3;
}

Expanding linear-gradient background unaffected by div layout

I have the following code. When you click on it (excuse the on-the-fly, inline onclick - on my page it is more properly set up), the background expands to the right.
Unfortunately as I am using a :before with display: inline-block, it is affecting the layout of the text inside.
It also is being affected by the padding property I have on the box. I could solve this by setting a negative margin: -16px on the :before element however the height of the :before element goes off:
div {
border: 1px solid teal;
height: 64px;
border-radius: 10px;
overflow: hidden;
padding: 16px;
}
div:before {
display: inline-block;
height: 100%;
width: 5%;
content: '';
background: linear-gradient(130deg, lightblue 40%, white 0%);
transition: .3s;
}
div.active:before {
width: 200%;
/* or 300% if you want the entire background to be "taken over" */
}
<div onclick="this.classList.toggle('active')">
<span>Hi! I'm text! nice to meet you!</span>
</div>
This is how I want it to look like (it looks fine here because there is no text to get in the way and no padding property - both of which I will need for my webpage):
div {
border: 1px solid teal;
height: 64px;
border-radius: 10px;
overflow: hidden;
}
div:before {
display: inline-block;
height: 100%;
width: 5%;
content: '';
background: linear-gradient(130deg, lightblue 40%, white 0%);
transition: .3s;
}
div.active:before {
width: 200%;
/* or 300% if you want the entire background to be "taken over" */
}
<div onclick="this.classList.toggle('active')">
</div>
Does anyone know how to remove a :before from the layout of a box? Ideally without using position as on my page based on some parent items to the above box, position gets a bit "funky." But if it's the only solution then so be it.
Simply make the background on the main element and play with background-size
div {
border: 1px solid teal;
height: 64px;
border-radius: 10px;
overflow: hidden;
padding: 16px;
background-image: linear-gradient(130deg, lightblue 40%, white 0%);
background-size:10% 100%;
background-position:left;
background-repeat:no-repeat;
transition:background 0.5s;
}
div.active{
background-size:300% 100%;
}
<div onclick="this.classList.toggle('active')">
<span>Hi! I'm text! nice to meet you!</span>
</div>
Not sure if this is what you're looking for:
div {
border: 1px solid teal;
height: 64px;
border-radius: 10px;
overflow: hidden;
position:relative;
}
div:before {
display: inline-block;
height: 100%;
width: 5%;
content: '';
background: linear-gradient(130deg, lightblue 40%, white 0%);
transition: .3s;
position:absolute;
}
div.active:before {
width: 200%;
/* or 300% if you want the entire background to be "taken over" */
}
div span{
position:absolute;
padding: 16px;
}
<div onclick="this.classList.toggle('active')">
<span>Hi! I'm text! nice to meet you!</span>
</div>
The only way to fix this without either removing the :before or using position is by adding the text to the content property of the :before,
that would result in code like:
HTML:
<div onclick="this.classList.toggle('active')"></div>
CSS:
div {
border: 1px solid teal;
height: 64px;
border-radius: 10px;
overflow: hidden;
padding: 16px;
}
div:before {
display: inline-block;
height: 100%;
width: 100%;
content: "Hi! I'm text! nice to meet you!";
background: linear-gradient(130deg, lightblue 5%, white 0%); /*Or whatever width you like*/
transition: .3s;
text-align: center;
line-height: 4;
}
div.active:before {
width: 100%;
background: linear-gradient(130deg, lightblue 75%, white 0%); /*Or whatever width you like*/
/* or 100% lightblue if you want the entire background to be "taken over" */
}
But most accessibility hard- and software is incapable of handling a :before correctly.
So why not set the background on either the div or the span?
CSS:
span {
width: 100%;
background: linear-gradient(130deg, lightblue 5%, white 0%); /*Or whatever width you like*/
transition: .3s;
text-align: center;
line-height: 4;
}
span.active {
background: linear-gradient(130deg, lightblue 75%, white 0%); /*Or whatever width you like*/
}
which results in the same background effect, with the text centered.

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

Transparent trapezoidal buttons with border and centered text

I'm designing a site where trapezoids are crucial. I'm using the following code to achieve the effect I'm looking for, but am having issues with it: http://jsfiddle.net/9n9uh6f6/9/
The biggest problems are the mouseover area (because I'm using perspective transforms, the clickable area is skewed) and centering text within the shape.
Other than using perspective transforms, how can I make a shape that does the following:
Trapezoid with a colored border and transparent interior.
Trapezoid that can change color when a user hovers over it.
Trapezoid that houses text in the center of the shape.
Here's the CSS I'm using:
.prodcaptions {
width:136px;
height: 85px;
position:relative;
left:10%;
text-transform:uppercase;
text-align:center;
letter-spacing: 1.6px;
color: #000;
}
.prodcaptions:before {
content:"";
position:absolute;
border-radius:1px;
box-shadow:0 0 0 3px #27628e;
top:-5%;
bottom:-11%;
left:-1%;
right:-5%;
-webkit-transform:perspective(40em) rotateX(-45deg);
transform:perspective(40em) rotateX(-45deg);
}
.prodcaptions a {
z-index:999;
position:relative;
height: 85px;
display: block;
padding-top: 25px;
}
For this case, it would be better to use a skew transform to produce the shape than a rotation with perspective.
We can achieve the shape by using two pseudo-elements skewed in opposite directions and then position one at the left corner and the other at the right corner. Since only the pseudo-elements are skewed and not the main container, the text remains in its expected place (at center-middle).
This shape can (a) support dynamic width (b) have a colored border with transparent background (c) have the text in the center of the shape and (d) support change of background color when hovered on.
.trapezoid {
display: inline-block;
position: relative;
height: 100px;
width: auto;
color: #27628e;
border-top: 2px solid #27628e;
border-bottom: 2px solid #27628e;
line-height: 100px;
text-align: center;
white-space: nowrap;
text-transform: uppercase;
letter-spacing: 1.6px;
margin: 15px 250px; /* Just for demo */
}
.trapezoid:after,
.trapezoid:before {
position: absolute;
content: '';
top: -2px;
height: 100%;
width: 50%;
z-index: -1;
}
.trapezoid:before {
left: 0px;
border-left: 2px solid #27628e;
border-top: 2px solid #27628e;
transform-origin: left bottom;
transform: skew(10deg);
}
.trapezoid:after {
right: 0px;
border-right: 2px solid #27628e;
border-top: 2px solid #27628e;
transform-origin: right bottom;
transform: skew(-10deg);
}
.trapezoid:hover,
.trapezoid:hover:after,
.trapezoid:hover:before {
background: #27628e;
color: white;
}
/* Just for demo */
body {
background: linear-gradient(90deg, aliceblue, powderblue);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
Click Me!!!
You could also create the same shape using SVG and the angled sides look a tad more smoother while using SVG. The below snippet currently works only for a fixed size container. It should not be an issue as the code in question also has fixed dimensions.
.vector {
position: relative;
height: 100px;
width: -webkit-calc(100px * 1.36);
width: calc(100px * 1.36);
line-height: 100px;
margin: 0px auto; /* Just for demo */
}
svg {
height: 100%;
width: 100%:
}
polygon {
fill: transparent;
stroke-width: 2;
stroke: steelblue;
}
.vector a {
position: absolute;
display: block;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
text-decoration: none;
text-transform: uppercase;
letter-spacing: 1.6px;
color: steelblue;
text-align: center;
white-space: nowrap;
}
.vector:hover polygon {
fill: steelblue;
}
.vector:hover a {
color: white;
}
/* Just for demo */
body{
background: linear-gradient(90deg, aliceblue, powderblue);
}
<div class='vector'>
<svg viewBox='0 0 136 100' preserveaspectratio='none'>
<polygon points='1,2 18,98 118,98 135,2' />
</svg>
<a href='#'>Click Me!!!</a>
</div>

How to create parent div with opacity while keeping the opacity of the text at 100% [duplicate]

This question already has answers here:
How do I reduce the opacity of an element's background using CSS?
(29 answers)
Closed 9 years ago.
So I have a div with an opacity set with a background image. I want the text that pops up when hovering the div to stay 100%. Could anyone possibly help me with this? Any help would be greatly appreciated!
DEMO
<body>
<div id="container">
<div id="container_inner">
<div id="container_txt">
<p>WORLD OF WARCRAFT</p>
<p id="p_txt">This is a simple World of Warcraft styled div that has been done implementing html, css, and css3</p>
</div>
</div>
</div>
</body>
What I fiddled upon and came on conclusion though is this is what you need I think.
Below is CSS that you have to use.
Fiddle: Click HERE
Demo (Transparent background)
html, body {
margin: 0;
height: 100%;
background-color: #575980;
}
#container {
width: 200px;
height: 300px;
cursor: pointer;
overflow: hidden;
margin: 100px auto;
border: 1px solid #333;
background-color: #000;
box-shadow: 0px 2px 8px #111;
}
#container_inner {
opacity: .8;
margin: auto;
width: 200px;
height: 300px;
transition: .5s;
position: relative;
background-color: #FFF;
background-image: url('http://static.mmo-champion.com/mmoc/images/news/2010/march/ss973.jpg');
background-size: 200% 100%;
background-position: 60% 50%;
box-shadow: inset 0px 0px 0px 1px rgba(255, 255, 255, 0.5);
}
#container_inner:hover, #container_txt:hover {
opacity: 1;
}
#container_txt {
color: #fff;
height: 0px;
bottom: 0px;
width: 200px;
transition: .2s;
position: absolute;
font: normal 1em calibri;
background-color: rgba(0, 0, 0, 1);
}
#container_inner:hover #container_txt {
height: 100px;
opacity: 1;
}
p {
top: -5px;
padding: 0px 10px;
position: relative;
}
p a {
color: #fff;
text-decoration: none;
}
#p_txt {
top: -15px;
position: relative;
font-size: 12px;
}
Just for a better understanding:
This CSS changes the opacity of the complete element (background, border, text, containing child-elements, ...)
#container{
background-color: #000;
opacity: 0.5;
}
But this CSS changes the opacity of a color. And this "modified" color will be used for background.
#container{
background-color: rgba(0, 0, 0, 0.5);
}
The problem is that a child cannot be less opaque than its parent. In this case, instead of a background image, I would use a :after pseudo element to create the background, then put the background image/opacity/ whatever on that, and leave the parent alone.
I modified your fiddle to do this (http://jsfiddle.net/srfGg/4/), but the main key is:
#container_inner:after{
opacity:0.8;
transition:.2s;
content: "";
display:block;
color:#FFF;
height:100%;
width:100%;
position: aboslute;
top:0;left:0;right:0;bottom:0;
background-color: #FFF;
background-image: url('http://static.mmo-champion.com/mmoc/images/news/2010/march/ss973.jpg');
background-size: 200% 100%;
background-position: 60% 50%;
}
#container_inner:hover:after, #container_txt:hover {
opacity: 1;
}