Reputation: 105
I've created an 'underline' animation that uses an ::after pseudo-element underneath the link. Here is the code for the link and the pseudo-element:
Link
a {
position: relative;
}
::after
a:after {
content: '';
display: inline;
position: absolute;
height: 2px;
width: 0%;
background-color: #ce3f4f;
left: 0%;
bottom: 0px;
transition: all 0.2s ease;
}
a:hover::after {
width: 100%;
}
This all works fine when the link is on a single line, but if the link flows onto the next line then it only fills across the bottom of the first line, as seen here:
https://i.sstatic.net/7SX7o.jpg
If I inspect the element then it appears that the issue is not solvable, as the browser (in this case, Firefox) isn't selecting the entirety of the wrapped element:
https://i.sstatic.net/342GH.jpg
Is there a way of solving this purely with CSS, or is it a problem with the way the browser renders the objects? I have played around with a lot of white-space
, display
and position
configurations but to no avail.
Here's an example of the behaviour:
https://jsfiddle.net/57Lmkyf4/
Upvotes: 4
Views: 572
Reputation: 1397
This cannot be done with CSS. (I've implemented it using JS for links that wrap over not more than 2 lines: https://jsfiddle.net/6zm8L9jq/1/ - you can resize the frame to see it at work)
In my Chrome (39.0.2171.95) the underline under a wrapping a
doesn't work at all, while in FF it displays like in your screenshot above. Primarily this is because your a
element is inline (default), and when it wraps, any pseudo/child elements that depend on its width get 0
width in Chrome and the element's width on the first row in FF. Inline elements don't have control on their own width/height properties (eg, you can't set a width:100px
on them without changing them to block elements), and this also affects any absolutely positioned elements that depend on them for width/height.
If you call the window.getComputedStyle
method on the pseudo element in FF and Chrome, like:
var a = document.querySelector('a');
a.onmouseover = function(){
setTimeout(function(){
var width = window.getComputedStyle(a,':after').getPropertyValue('width');
console.log(width);
},300); //timeout so that animation to 100% width is completed
}
...in chrome you will see 0px
while in FF you will see 100%
- and neither will span to actual 100% of the parent. If you added a child element (eg a span
) to a
instead of a pseudo element, you could investigate the child's actual width after mouseover
by calling getBoundingClientRect().width
on the child, in which case again, in chrome you would see 0px
, and in FF the width of the part of the parent element falling on the first line.
You can change the a
element to display: inline-block
and it will work, but it will obviously no longer wrap.
Upvotes: 1