Multi-Line link animation on :before - css

Like in the question, I have a code
How to make this effect work on many text lines and not as it is now - the effect appears only in 1 of e.g. 2 text lines (like example)
:root {
--00a3a3: #00a3a3;
}
a {
position: relative;
text-decoration: none; /* For Example */
}
a:before {
content: "";
position: absolute;
width: 100%;
height: 2px;
bottom: 0;
left: 0;
background-color: var(--00a3a3);
visibility: hidden;
-webkit-transform: scaleX(0);
transform: scaleX(0);
-webkit-transition: all 0.3s ease-in-out 0s;
transition: all 0.3s ease-in-out 0s;
}
a:hover:before {
visibility: visible;
-webkit-transform: scaleX(1);
transform: scaleX(1);
}
test
<br>
<br>
<a href="#">test
<br>
test2
</a>

Use background combined with box-decoration-break to have a duplicated effect on each line
:root {
--00a3a3: #00a3a3;
}
a {
text-decoration: none;
background:linear-gradient(var(--00a3a3),var(--00a3a3)) bottom center no-repeat;
background-size:0% 2px;
transition: all 0.3s ease-in-out 0s;
/* Remove the below to see the diffrence */
-webkit-box-decoration-break: clone;
box-decoration-break: clone;
}
a:hover{
background-size:100% 2px;
}
test
<br>
<br>
<a href="#">test
<br>
test2
</a>

Get rid of the ::before. Instead apply a background-image to the <a>.
:root {
--00a3a3: #00a3a3;
}
a {
position: relative;
text-decoration: none; /* For Example */
background-image: linear-gradient(#00a3a3, #00a3a3);
background-position: 50% 100%;
background-repeat: no-repeat;
background-size: 0% 2px;
transition: background-size .3s;
}
a:hover {
background-size: 100% 2px;
}
test
<br>
<br>
<a href="#">test
<br>
test2
</a>
Edit:
The problem is that the :before pseudo-element doesn't know that your <a> is two lines. It's just adding a new block element inside it and taking the shape you give it.
If you know that your links will always be two lines, you might be able to get away with using an :after for the second line, like this:
:root {
--00a3a3: #00a3a3;
}
a {
position: relative;
text-decoration: none;
/* For Example */
}
a:before,
a:after {
content: "";
position: absolute;
width: 100%;
height: 2px;
left: 0;
background-color: var(--00a3a3);
visibility: hidden;
-webkit-transform: scaleX(0);
transform: scaleX(0);
-webkit-transition: all 0.3s ease-in-out 0s;
transition: all 0.3s ease-in-out 0s;
}
a:before {
bottom: 0;
}
a:after {
bottom: 1em;
}
a:hover:before,
a:hover:after {
visibility: visible;
-webkit-transform: scaleX(1);
transform: scaleX(1);
}
test
<br>
<br>
<a href="#">test
<br>
test2
</a>
(But you're probably better off restructuring your code to remove the :before.)

Related

How to animate a link underline with border-bottom, so that there is space between the link text and the underline?

How could I animate the link underline with using border-bottom, so that there is space between the text and the underline?
I know how to do it in the following way, so that the default text-decoration element is animated. But I would like to have space between the link and the underline, that is why I think I need to use border-bottom. But I can't get the border-bottom work with the transition animation. How could I do this? I tried looking for other solutions, but couldn't find any. Thanks!
h2 > a {
position: relative;
color: #000;
text-decoration: none;
}
h2 > a:before {
content: "";
position: absolute;
width: 100%;
height: 2px;
bottom: 0;
left: 0;
background-color: #000;
visibility: hidden;
-webkit-transform: scaleX(0);
transform: scaleX(0);
-webkit-transition: all 0.3s ease-in-out 0s;
transition: all 0.3s ease-in-out 0s;
}
h2 > a:hover:before {
visibility: visible;
-webkit-transform: scaleX(1);
transform: scaleX(1);
}
you can fake an animated border via background and background-size:
a {
padding-bottom: 5px;
/* set here size + gap size from text */
background: linear-gradient(0deg, currentcolor, currentcolor) bottom center no-repeat;
background-size: 0px 3px;
transition: 0.5s;
text-decoration: none;
}
a:hover {
background-size: 100% 3px;
}
a[class] {
color: gray;
}
a.tst {
color: purple;
background: linear-gradient(0deg, currentcolor, currentcolor) bottom center no-repeat, linear-gradient(0deg, turquoise, turquoise) center calc(100% - 2px) no-repeat;
background-size: 0px 2px;
}
a.tst:hover {
background-size: 100% 2px;
}
<a href>kake animated border</a>
<a href class> why currentcolor ?</a>
<a href class="tst">mix of colors ?</a>
The code you've presented uses a pseudo-element not the default text-decoration. Since the pseudo element is positioned absolutely, you can change the distance easily. Change the a:before bottom to -5px or whatever negative value fits the distance that you want:
a {
position: relative;
color: #000;
text-decoration: none;
}
a:before {
content: "";
position: absolute;
width: 100%;
height: 2px;
bottom: -5px;
left: 0;
background-color: #000;
visibility: hidden;
-webkit-transform: scaleX(0);
transform: scaleX(0);
-webkit-transition: all 0.3s ease-in-out 0s;
transition: all 0.3s ease-in-out 0s;
}
a:hover:before {
visibility: visible;
-webkit-transform: scaleX(1);
transform: scaleX(1);
}
Long long text

CSS Hyperlink Animation fails when words wrap at the margin

Here's an example of a CSS hyperlink animation from this article:
a {
position: relative;
color: #000;
text-decoration: none;
}
a:hover {
color: #F00;
}
a:before {
content: "";
position: absolute;
width: 100%;
height: 2px;
bottom: 0;
left: 0;
background-color: #F00;
visibility: hidden;
-webkit-transform: scaleX(0);
transform: scaleX(0);
-webkit-transition: all 0.3s ease-in-out 0s;
transition: all 0.3s ease-in-out 0s;
}
a:hover:before {
visibility: visible;
-webkit-transform: scaleX(1);
transform: scaleX(1);
}
<p>As armas e os barões assinalados, que da ocidental praia lusitana, por mares nunca dantes navegados, passaram ainda além da trapobana.</p>
The effect is of the underline progressively appearing (through scaling) form the center to the outline. This is a nice effect accomplished by the :before trick.
However, it completely breaks up when hyperlinks wrap at the margin, and I can't think of any way to fix it...
The problem is that the pseudo-element won't be applied over multiple lines. One workround could be to prevent those line-breaks of the link content.
To achieve this simply add display: inline-block to the a tag
a {
position: relative;
color: #000;
text-decoration: none;
display: inline-block;
}
a:hover {
color: #F00;
}
a:before {
content: "";
position: absolute;
width: 100%;
height: 2px;
bottom: 0;
left: 0;
background-color: #F00;
visibility: hidden;
-webkit-transform: scaleX(0);
transform: scaleX(0);
-webkit-transition: all 0.3s ease-in-out 0s;
transition: all 0.3s ease-in-out 0s;
}
a:hover:before {
visibility: visible;
-webkit-transform: scaleX(1);
transform: scaleX(1);
}
<p>As armas e os barões assinalados, que da ocidental praia lusitana, por mares nunca dantes navegados, passaram ainda além da trapobana As armas e os barões assinalados, que da.</p>
As the psuedo elements wont take multiple lines. you can use white-space: nowrap; to prevent it from wrapping to the next line and animation will look consistent. Even though nothing works as good as like an underline
a {
position: relative;
color: #000;
text-decoration: none;
white-space: nowrap;
}
a:hover {
color: #F00;
}
a:before {
content: "";
position: absolute;
width: 100%;
height: 2px;
bottom: 0;
left: 0;
background-color: #F00;
visibility: hidden;
-webkit-transform: scaleX(0);
transform: scaleX(0);
-webkit-transition: all 0.3s ease-in-out 0s;
transition: all 0.3s ease-in-out 0s;
}
a:hover:before {
visibility: visible;
-webkit-transform: scaleX(1);
transform: scaleX(1);
}
<p>As armas e os barões assinalados, que da ocidental praia lusitana, por mares nunca dantes navegados, passaram ainda além da trapobana.</p>

CSS - translate3d doesn't seem to do anything?

I don't get this, it seems like a bug, but it's consistent through several browsers. So the bug must be in my own head.
Basically, I've got this block with an image and some text.
The heading inside this block is composed of several span elements with each character in them. I want to fade these in, with opacity 0 to 1 and move them about 30 pixels on hover, with a slight delay on each span. This is no problem. But for some reason, only opacity seems to work, not translate3d.
I've got a jsfiddle to describe it:
https://jsfiddle.net/w5Lgdgt9/5/
HTML:
<div class="tiles-wrapper">
<article class="tiles-block">
<a href="">
<img src="https://orig06.deviantart.net/91ee/f/2008/209/1/9/cat_stock_002_by_pc_stock.jpg">
<h3>
<span>L</span>
<span>o</span>
<span>r</span>
<span>e</span>
<span>m</span>
<span></span>
<span>i</span>
<span>p</span>
<span>s</span>
</h3>
</a>
</article>
</div>
CSS:
.tiles-wrapper {
position: relative;
overflow: hidden;
}
.tiles-block {
width:100%;
}
img {
width: 100%;
transition: transform .9s ease;
transform: scale(1);
}
span {
position: relative;
transition: opacity .3s, transform .3s ease;
opacity: 0;
transform: translate3d(0,-30px,0);
color:#000;
font-weight: bold;
}
h3 {
position: absolute;
left: 0;
top: 0;
width: 100%;
margin: 0;
text-align: center;
z-index: 1;
transition: opacity .3s ease, transform .3s ease;
opacity: 0;
transform: translate3d(0,40px,0);
padding: 70px;
font-size: 24px;
}
a {
display:block;
margin: 0;
position: relative;
}
h3 span:nth-of-type(1) {
transition-delay: .2s;
}
h3 span:nth-of-type(2) {
transition-delay: .4s;
}
h3 span:nth-of-type(3) {
transition-delay: .6s;
}
h3 span:nth-of-type(4) {
transition-delay: .8s;
}
h3 span:nth-of-type(5) {
transition-delay: 1s;
}
h3 span:nth-of-type(6) {
transition-delay: 1.2s;
}
h3 span:nth-of-type(7) {
transition-delay: 1.4s;
}
h3 span:nth-of-type(8) {
transition-delay: 1.6s;
}
h3 span:nth-of-type(9) {
transition-delay: 1.8s;
}
h3 span:nth-of-type(9) {
transition-delay: 2s;
}
a:hover span{
opacity: 1;
transform: translate3d(0,0,0);
}
a:hover h3 {
opacity: 1; transform: translate3d(0,0,0);
}
a:hover img{ transform: scale(1.1); }
Sorry about the horrible CSS code, I usually use SASS and I couldn't get it to work on jsfiddle. Also, don't worry about the prefixes on the transition stuff, gulp takes care of that for me, so that's not the problem.
Found out, it's because the span elements hadn't been set to inline-block. As translate and translate3d only works on block elements. Stupid me
Use:
translate
instead of:
translate3d
Your fiddle updated with this minor change works just fine: https://jsfiddle.net/w5Lgdgt9/6/

Reveal Icon Button - Bootstrap 3

How to create a reveal icon inside button on hover in TB3. I tried to mimic this behavior using CSS transitions and position property. But I essentially need is to have a separate background color for icon and button. Here is what I am doing right now.
HTML Markup
<button class="btn btn-dark icon-revealed">
<span class="glyphicon glyphicon-cloud-download"></span>
Download
</button>
CSS Code
.btn.icon-revealed > span {
left: -30px;
width: 0;
-webkit-transition: all .5s ease-in-out;
-moz-transition: all .5s ease-in-out;
-o-transition: all .5s ease-in-out;
-ms-transition: all .5s ease-in-out;
}
.btn.icon-revealed:hover > span {
width: 20%;
-webkit-transform: translate(2em,0);
-moz-transform: translate(2em,0);
-o-transform: translate(2em,0);
-ms-transform: translate(2em,0);
}
What I want to Achieve
Notice the background color of icon and button changed on hover state. I could not able to do that. How can I achieve this in TB3?
Here's an alternative way that smooths out the transition.
.btn-dark {
border: none;
font-family: inherit;
font-size: inherit;
color: #fff;
background: none;
padding: 15px 30px;
display: inline-block;
text-transform: uppercase;
letter-spacing: 1px;
font-weight: 500;
outline: none;
position: relative;
-webkit-transition: all 0.3s;
-moz-transition: all 0.3s;
transition: all 0.3s;
}
.btn-dark:after {
content: '';
position: absolute;
z-index: -1;
-webkit-transition: all 0.3s;
-moz-transition: all 0.3s;
transition: all 0.3s;
}
.btn-icon {
background: #4E7878;
color: #fff;
line-height: 20px;
font-size: 14px;
overflow: hidden;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
backface-visibility: hidden;
}
.btn-icon span {
display: inline-block;
width: 100%;
height: 100%;
-webkit-transition: all 0.3s;
-webkit-backface-visibility: hidden;
-moz-transition: all 0.3s;
-moz-backface-visibility: hidden;
transition: all 0.3s;
backface-visibility: hidden;
}
.btn-icon:before {
background: #4A6B6B;
position: absolute;
height: 100%;
width: 30%;
line-height: 2.5;
font-size: 150%;
-webkit-transition: all 0.3s;
-moz-transition: all 0.3s;
transition: all 0.3s;
}
.btn-download:hover span {
-webkit-transform: translateX(25%);
-moz-transform: translateX(25%);
-ms-transform: translateX(25%);
transform: translateX(25%);
color: #fff;
}
.btn-download:before {
left: -100%;
top: 0;
}
.btn-download:hover:before {
left: 0%;
}
.icon-reveal:before {
content: "\e197";
font-family: 'Glyphicons Halflings';
color: #fff;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
<hr>
<div class="container">
<button class="btn-dark btn-icon btn-download icon-reveal"><span> Download</span>
</button>
</div>
You can create that effect using multiple backgrounds with linear-gradient. Code explanantion in comments
.btn.icon-revealed {
margin: 10px; /* Added for SO snippet, not required */
width: 115px; /* Added fixed width for avoiding jump */
}
.btn.icon-revealed > span {
left: -40px;
width: 0;
-webkit-transition: all .5s ease-in-out;
-moz-transition: all .5s ease-in-out;
-o-transition: all .5s ease-in-out;
-ms-transition: all .5s ease-in-out;
}
.btn.icon-revealed:hover > span {
width: 20%;
-webkit-transform: translate(2.5em, 0);
-moz-transform: translate(2.5em, 0);
-o-transform: translate(2.5em, 0);
-ms-transform: translate(2.5em, 0);
}
/* Added code */
.btn.icon-revealed {
background: #53777A;
color: #fff;
}
.btn.icon-revealed:hover {
background: linear-gradient(to right, #4B6B6E 0%, #4B6B6E 30%, #53777A 30%);
/* Start color---^, End at 30%-^, ^-- Start second color */
color: #fff;
}
.btn.icon-revealed:hover .text {
padding-left: 5px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
<button class="btn btn-dark icon-revealed">
<span class="glyphicon glyphicon-cloud-download"></span>
<span class="text">Download</span>
</button>

Hover effect : expand bottom border

I'm trying to get a transition hover effect on border that the border expands on hover.
h1 {
color: #666;
}
h1:after {
position: absolute;
left: 10px;
content: '';
height: 40px;
width: 275px;
border-bottom: solid 3px #019fb6;
transition: left 250ms ease-in-out, right 250ms ease-in-out;
opacity: 0;
}
h1:hover:after {
opacity: 1;
}
<h1>CSS IS AWESOME</h1>
I've tried this on Jsfiddle
To expand the bottom border on hover, you can use transform:scaleX'(); (mdn reference) and transition it from 0 to 1 on the hover state.
Here is an example of what the border hover effect can look like :
The border and transition are set on a pseudo element to prevent transitioning the text and avoid adding markup.
To expand the bottom border from left or right, you can change the transform-origin property to the left or right of the pseudo element:
h1 { color: #666;display:inline-block; margin:0;text-transform:uppercase; }
h1:after {
display:block;
content: '';
border-bottom: solid 3px #019fb6;
transform: scaleX(0);
transition: transform 250ms ease-in-out;
}
h1:hover:after { transform: scaleX(1); }
h1.fromRight:after{ transform-origin:100% 50%; }
h1.fromLeft:after{ transform-origin: 0% 50%; }
<h1 class="fromCenter">Expand from center</h1><br/>
<h1 class="fromRight">Expand from right</h1><br/>
<h1 class="fromLeft">Expand from left</h1>
Note : You need to add vendor prefixes to maximize browser support (see canIuse).
Expand bottom border on hover with 2 lines
You can achieve this effect when the text spans on 2 lines. The before pseudo element is absolutely positioned to make underline of the first line with bottom:1.2em;:
h1 { position:relative;color: #666;display:inline-block; margin:0;text-transform:uppercase;text-align:center;line-height:1.2em; }
h1:after, h1:before {
display:block;
content: '';
border-bottom: solid 3px #019fb6;
transform: scaleX(0);
transition: transform 250ms ease-in-out;
}
h1:before{
position:absolute;
bottom:1.2em; left:0;
width:100%;
}
.ef2:hover:after {
transition-delay:150ms;
}
h1:hover:after, h1:hover:before { transform: scaleX(1); }
<h1>Expand border<br/>on two lines</h1>
<br/>
<br/>
<h1 class="ef2">Expand border<br/>effect two</h1>
Different transition direction on hover in and out :
The point is to change the transform-origin position from one side to the other on the hover state. This way the bottom boder enters from one side on hover and exits on the other when the element isn't hovered anymore.
Here is a demo :
h1 { color: #666;display:inline-block; margin:0;text-transform:uppercase; }
h1:after {
display:block;
content: '';
border-bottom: solid 3px #019fb6;
transform: scaleX(0);
transition: transform 250ms ease-in-out;
}
h1.fromLeft:after{ transform-origin: 100% 50%; }
h1.fromRight:after{ transform-origin: 0% 50%; }
h1.fromLeft:hover:after{ transform: scaleX(1); transform-origin: 0% 50%; }
h1.fromRight:hover:after{ transform: scaleX(1); transform-origin: 100% 50%; }
<h1 class="fromRight">Expand from right</h1><br/>
<h1 class="fromLeft">Expand from left</h1>
We can do this with only background. No pseudo-element needed. This is more flexible.
h1 {
/* you can change these variables to control the border */
--border-color: purple;
--border-width: 5px;
--bottom-distance: 0px; /* you can increase this */
color: #666;
display: inline-block;
background-image: linear-gradient(var(--border-color), var(--border-color));
background-size: 0% var(--border-width);
background-repeat: no-repeat;
transition: background-size 0.3s;
margin: 5px 0;
}
.fromCenter {
background-position: 50% calc(100% - var(--bottom-distance));
}
.fromRight {
background-position: 100% calc(100% - var(--bottom-distance));
}
.fromLeft {
background-position: 0 calc(100% - var(--bottom-distance))
}
h1:hover {
background-size: 100% var(--border-width);
}
<h1 class="fromCenter">Expand from center</h1><br/>
<h1 class="fromRight">Expand from right</h1><br/>
<h1 class="fromLeft">Expand from left</h1>
Multiple line animation:
h1 {
/* you can change these variables to control the border */
--border-color: purple;
--border-width: 5px;
--bottom-distance: 0px; /* you can increase this */
color: #666;
display: inline; /* should be 'inline' for multiple line animation */
background-image: linear-gradient(var(--border-color), var(--border-color));
background-size: 0% var(--border-width);
background-repeat: no-repeat;
transition: background-size 0.5s;
}
.fromCenter {
background-position: 50% calc(100% - var(--bottom-distance));
}
.fromRight {
background-position: 100% calc(100% - var(--bottom-distance));
}
.fromLeft {
background-position: 0 calc(100% - var(--bottom-distance))
}
h1:hover {
background-size: 100% var(--border-width);
}
<h1 class="fromLeft">Expand from <br>left with <br>multiple line</h1>
simple and lightweight version
li {
margin-bottom: 10px;
}
.cool-link {
display: inline-block;
color: #000;
text-decoration: none;
}
.cool-link::after {
content: '';
display: block;
width: 0;
height: 2px;
background: #000;
transition: width .3s;
}
.cool-link:hover::after {
width: 100%;
//transition: width .3s;
}
<ul>
<li><a class="cool-link" href="#">A cool link</a></li>
<li><a class="cool-link" href="#">A cool link</a></li>
<li><a class="cool-link" href="#">A cool link</a></li>
</ul>
I know this is an old post and it is already answered but you might like the following effect too.
<div class="cd-single-point">
<a class="cd-img-replace" href="#0"></a>
</div>
.cd-single-point {
position: absolute;
list-style-type: none;
left: 20px;
top: 20px;
}
.cd-single-point>a {
position: relative;
z-index: 2;
display: block;
width: 10px;
height: 10px;
border-radius: 50%;
background: #0079ff;
-webkit-transition: background-color 0.2s;
-moz-transition: background-color 0.2s;
-o-transition: background-color 0.2s;
transition: background-color 0.2s;
}
.cd-single-point::after {
content: '';
position: absolute;
border-radius: 50%;
width: 100%;
height: 100%;
top: 0;
left: 0;
animation: cd-pulse 2s infinite;
}
#keyframes cd-pulse
{
0% {box-shadow:0 0 0 0 #0079ff}
100%{box-shadow:0 0 0 20px rgba(255,150,44,0)}
}
DEMO
h1 {
color: #666;
display:inline-block;
margin:0;
text-transform:uppercase;
}
h1:after {
display:block;
content: '';
border-bottom: solid 3px #92a8d1;
transform: scaleX(0);
transition: transform 800ms ease-in-out;
}
h1:hover:after {
transform: scaleX(1);
}
<h1 class="fromCenter">Hover Over Me</h1><br/>
we can do using simple transition effect.
HTML
<h1>CSS IS AWESOME</h1>
CSS
h1 {
color: #666;
position: relative;
display: inline-block;
}
h1:after {
position: absolute;
left: 50%;
content: '';
height: 40px;
height: 5px;
background: #f00;
transition: all 0.5s linear;
width: 0;
bottom: 0;
}
h1:hover:after {
width: 270px;
margin-left: -135px;
}
Link to Fiddle
h1 {
/* you can change these variables to control the border */
--border-color: purple;
--border-width: 5px;
--bottom-distance: 0px; /* you can increase this */
color: #666;
display: inline-block;
background-image: linear-gradient(var(--border-color), var(--border-color));
background-size: 0% var(--border-width);
background-repeat: no-repeat;
transition: background-size 0.3s;
margin: 5px 0;
}
.fromCenter {
background-position: 50% calc(100% - var(--bottom-distance));
}
.fromRight {
background-position: 100% calc(100% - var(--bottom-distance));
}
.fromLeft {
background-position: 0 calc(100% - var(--bottom-distance))
}
h1:hover {
background-size: 100% var(--border-width);
}
<h1 class="fromCenter">Expand from center</h1><br/>
<h1 class="fromRight">Expand from right</h1><br/>
<h1 class="fromLeft">Expand from left</h1>
transition: all 1000ms ease-in-out;
Demo
or are you looking for this
Demo2
h1 {
color: #666;
}
h1:after {
position: absolute;
left: 10px;
content: '';
height: 40px;
width: 275px;
border-bottom: solid 3px #019fb6;
transition: all 550ms ease-in-out;
border-bottom-width: 0px;
}
h1:hover:after {
border-bottom-width: 5px;
}
<h1>CSS IS AWESOME</h1>

Resources