Animate a line under a hyperlink using only CSS [duplicate] - css

This question already has answers here:
How to animate underline from left to right?
(3 answers)
Closed 2 years ago.
I'm trying to animate a line in a particular way (see the following gif for a visual representation) under a hyperlink using the following code structure:
.navlink {
position: relative;
color: white;
}
.navlink a {
display: inline-block;
margin: 0;
text-decoration: none;
}
.navlink a::after {
display: block;
content: '';
border-bottom: solid 0.2vmax red;
transform: scaleX(0);
transition: transform 250ms ease-in-out;
}
.navlink a:hover::after {
animation: scaleup 3s forwards;
}
#keyframes scaleup {
50% {
transform: scaleX(1)
}
100% {
transform-origin: 50% 0, scaleX(0)
}
}
.navlink a:after {
transform-origin: 0% 50%;
}
<nav id="main-nav">
<div class="main-nav-content">
<div class="navlink">
<a href="/aboutus.html">
<span>About Us</span>
</a>
</div>
</div>
</nav>
I can get the line to animate in one direction OK but having problem with the second half of the animation. Can anyone help me understand a better way to do this using only CSS?

You might do it using translateX, so you wouldn't need to switch transform-origin:
.navlink {
position: relative;
color: white;
}
.navlink a {
display: inline-block;
margin: 0;
overflow: hidden;
text-decoration: none;
}
.navlink a:after {
display: block;
content: '';
border-bottom: solid 0.2vmax;
transform: translate(-110%);
transition: transform 250ms ease-in-out;
}
.navlink a:hover:after {
animation: scaleup 3s forwards;
}
#keyframes scaleup {
50% {
transform: translate(110%)
}
}
.navlink a:after {
transform-origin: 0% 50%;
}
<nav id="main-nav">
<div class="main-nav-content">
<div class="navlink">
<a href="/aboutus.html">
<span>About Us</span>
</a>
</div>
</div>
</nav>

Used different approach, pseudo element of parents width floats from left to right and back
.navlink {
position: relative;
color: white;
}
.navlink a {
display: inline-block;
margin: 0;
text-decoration: none;
position: relative;
overflow: hidden;
padding-bottom: 5px;
}
.navlink span::after {
position: absolute;
left: -100%;
display: block;
content: ' ';
border-bottom: solid 0.2vmax red;
height: 2px;
width: 100%;
transition: left 500ms linear;
left: -100%;
}
.navlink a:hover span::after {
transition: left 500ms linear;
left: 100%;
}
<nav id="main-nav">
<div class="main-nav-content">
<div class="navlink">
<a href="/aboutus.html">
<span>About Us</span>
</a>
</div>
</div>
</nav>

Related

Unable to click on items in a css hamburger menu

I'm building a hamburger menu for a mobile website using only html and css. You can view the code here on codepen.io.
<html>
<body>
<nav>
<button class="hamburger"><span></span></button>
<div class="close"></div>
<ul class="menu">
<li>Page1</li>
<li>Page2</li>
<li>Page3</li>
<li>Page4</li>
<li>Google</li>
</ul>
</nav>
</body>
</html>
As you can see from line 106 in the css part
.hamburger:focus ~ .menu {
visibility: visible;
}
the menu is visible when the button is in focus. The Problem is that as soon as you click on a menu item, the button gets out of focus and the menu disappears before the click can be processed.
I already tried to write rules for the focussed menu, but it did not help.
Please let me know if you need any additional information.
Thank you in advance for your effort.
add transition visibility on your menu class. see the updated class below.
.menu {
position: absolute;
margin: 0;
padding: 10px;
width: auto;
height: auto;
visibility: hidden;
list-style: none;
background-color: #333;
transition: visibility 0.5s;
}
.menu a {
color: #87BF58;
display: block;
text-decoration: none;
}
.hamburger {
display: block;
position: relative;
overflow: hidden;
margin: 0;
padding: 0;
height: 3rem;
width: 3rem;
z-index: 500;
text-indent: 0;
appearance: none;
box-shadow: none;
border-radius: 0;
border: none;
cursor: pointer;
transition: background 0.3s;
background-color: yellowgreen;
}
.hamburger:focus {
outline: none;
background-color: green;
}
.hamburger span {
display: block;
position: absolute;
top: 45%;
left: 25%;
right: 25%;
height: 10%;
background: white;
transition: background 0s 0.3s;
}
.hamburger span::before,
.hamburger span::after {
position: absolute;
display: block;
left: 0;
width: 100%;
height: 100%;
background-color: #fff;
content: "";
transition-duration: 0.3s, 0.3s;
transition-delay: 0.3s, 0s;
}
.hamburger span::before {
top: -210%;
transition-property: top, transform;
}
.hamburger span::after {
bottom: -210%;
transition-property: bottom, transform;
}
.hamburger:focus span {
background: none;
}
.hamburger:focus span::before {
top: 0;
transform: rotate(45deg);
}
.hamburger:focus span::after {
bottom: 0;
transform: rotate(-45deg);
}
.hamburger:focus span::before,
.hamburger:focus span::after {
transition-delay: 0s, 0.3s;
}
.close {
position: absolute;
height: 3rem;
width: 3rem;
margin-top: -3rem;
z-index: 501;
background-color: transparent;
cursor: pointer;
visibility: hidden;
}
.hamburger:focus ~ .menu {
visibility: visible;
}
.hamburger:focus ~ .close {
visibility: visible;
}
<nav>
<button class="hamburger"><span></span></button>
<div class="close"></div>
<ul class="menu">
<li>Page1</li>
<li>Page2</li>
<li>Page3</li>
<li>Page4</li>
<li>Google</li>
</ul>
</nav>

CSS transform scale breaks image overlay

HTML Markup:
<div class="item">
<a href="url">
<img src="photo.jpg" />
</a>
</div>
This CSS zooms the image on hover:
.item a img {
transition: all 0.2s linear;
}
.item a:hover img {
transform: scale(1.05);
}
This CSS adds an overlay on hover:
.item a {
position: relative;
}
.item a:before {
content: "";
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: none no-repeat center center;
transition: all .3s linear;
}
.item a:hover:before {
background:rgba(0,0,0, 0.5) url('img/zoom.png') no-repeat center center;
}
Each one works fine by itself. However, when I try to use both bits of CSS, only the zoom works; the overlay is broken.
Simply, how can I write the CSS to combine these two effects?
You could try adding z-index:1 to the the absolute positioned element.
.item a img {
transition: all 0.2s linear;
}
.item a:hover img {
transform: scale(1.05);
vertical-align: top;
}
.item a {
position: relative;
display: inline-block;
}
.item a:before {
content: "";
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: none no-repeat center center;
transition: all .3s linear;
z-index: 1;
}
.item a:hover:before {
background: rgba(0, 0, 0, 0.5) url('//dummyimage.com/50') no-repeat center center;
}
<div class="item">
<a href="url">
<img src="//dummyimage.com/200" />
</a>
</div>

hover effect data-letters text-align

Hello i try to make a hover effect on my menu list with data-letters, so it' s work really good but i want to make it in text-align: right, the problem is that when i add it to my menu-item, i can' t see the data-letters :/
anyone have a solution ?
there is my code:
.link {
outline: none;
text-decoration: none;
position: relative;
color: #9e9ba4;
display:inline-block;
}
.link--over {
text-transform: uppercase;
overflow: hidden;
color: #c5c2b8;
}
.link--over:hover {
color: #c5c2b8;
}
.link--over::after {
content: '';
position: absolute;
height: 3px;
width: 100%;
top: 20%;
margin-top: -1.5px;
right: 0;
background: rgba(51,51,51,1);
-webkit-transform: translate3d(-100%,0,0);
transform: translate3d(-100%,0,0);
-webkit-transition: -webkit-transform 0.4s;
transition: transform 0.4s;
-webkit-transition-timing-function: cubic-bezier(0.7,0,0.3,1);
transition-timing-function: cubic-bezier(0.7,0,0.3,1);
}
.link--over:hover::after {
-webkit-transform: translate3d(100%,0,0);
transform: translate3d(100%,0,0);
}
.link--over::before {
content: attr(data-letters);
position: absolute;
z-index: 150;
overflow: hidden;
display:block;
color: #424242;
white-space: nowrap;
letter-spacing:10px;
width: 0%;
-webkit-transition: width 0.4s 0.3s;
transition: width 0.4s 0.3s;
}
.link--over:hover::before {
width: 100%;
}
.menu-item{
position:absolute;
left:50%;
margin-left:-50px;
margin-top:20%;
width:150px;
text-align:right;
}
.menu-item li {
position:relative;
width:100%;
letter-spacing:10px;
margin-bottom:40px;
}
#en-cours{
color:rgba(51,51,51,1);
}
<ul class="menu-item">
<a id="en-cours" class="link link--over" href="index.html" data-letters="works"><li>works</li></a>
<a class="link link--over" href="#" data-letters="about"><li>about</li></a>
<a class="link link--over" href="#" data-letters="contact"><li>contact</li></a>
</ul>
Would you be against throwing some tags between each item? I also added text-align:right to many CSS items:
.link {
outline: none;
text-decoration: none;
position: relative;
color: #9e9ba4;
display:inline-block;
}
.link--over {
text-transform: uppercase;
overflow: hidden;
color: #c5c2b8;
text-align: right;
}
.link--over:hover {
color: #c5c2b8;
}
.link--over::after {
content: '';
position: absolute;
height: 3px;
width: 100%;
top: 20%;
margin-top: -1.5px;
right: 0;
background: rgba(51,51,51,1);
-webkit-transform: translate3d(-100%,0,0);
transform: translate3d(-100%,0,0);
-webkit-transition: -webkit-transform 0.4s;
transition: transform 0.4s;
-webkit-transition-timing-function: cubic-bezier(0.7,0,0.3,1);
transition-timing-function: cubic-bezier(0.7,0,0.3,1);
text-align: right;
}
.link--over:hover::after {
-webkit-transform: translate3d(100%,0,0);
transform: translate3d(100%,0,0);
}
.link--over::before {
content: attr(data-letters);
position: absolute;
z-index: 150;
overflow: hidden;
color: #424242;
white-space: nowrap;
letter-spacing:10px;
width: 0%;
-webkit-transition: width 0.4s 0.3s;
transition: width 0.4s 0.3s;
text-align: right;
}
.link--over:hover::before {
width: 100%;
text-align: right;
}
.menu-item{
position:absolute;
left:50%;
margin-left:-50px;
margin-top:20%;
width:150px;
}
.menu-item li {
position:relative;
width:100%;
letter-spacing:10px;
margin-bottom:40px;
text-align: right;
}
#en-cours{
color:rgba(51,51,51,1);
}
<ul class="menu-item">
<a id="en-cours" class="link link--over menu-item" href="index.html" data-letters="works"><li>works</li></a>
<br>
<a class="link link--over menu-item" href="#" data-letters="about"><li>about</li></a>
<br>
<a class="link link--over menu-item" href="#" data-letters="contact"><li>contact</li></a>
</ul>

Pure CSS hover menu

I am trying to make an basic, preferrably no javascript, hover drop down menu for a navigational bar and it appears when it is hovered over, except it disappears when you scroll off of it. I have experimented with it and can't seem to figure out how to fix it.
Here is the code:
HTML:
<div tabindex="0" class="locations-menu" id="home-menu">
<div class="arrow">
</div>
<ul class="locations-menu-content" id="locations-header">
<br>
<a class="button" href="location1.html">Location #1</a><br>
<a class="button" href="location2.html">Location #2</a><br>
<a class="button" href="location3.html">Location #3</a><br>
</ul>
</div>
</div>
CSS:
.button {
font-family:"Trebuchet MS";
font-size:14px;
text-decoration:none;
color:#3D3D3D;
}
.arrow {
top:140%;
background-color:#648FBD;
position:absolute;
height:50%;
width:30%;
opacity:0;
visibility:hidden;
-ms-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
.locations-menu {
position: absolute;
display: inline-block;
height:50px;
top:3%;
left:30%;
}
.locations-menu:before {
content: "Locations";
font-family:"Trebuchet MS";
font-size:24px;
}
.locations-menu:focus {
pointer-events: none;
}
.locations-menu:hover .arrow {
opacity: 1;
transition: visibility 2s;
visibility: visible;
pointer-events: auto;
}
.locations-menu-content:hover .locations-menu-content {
opacity: 1;
visibility: visible;
pointer-events:auto;
}
.locations-menu:hover .locations-menu-content {
opacity: 1;
transition: visibility 2s;
visibility: visible;
pointer-events: auto;
}
.locations-menu-content {
background-color:#648FBD;
top:125%;
left:-15%;
position:absolute;
z-index: 1;
width:200%;
height:200%;
text-decoration:none;
opacity: 0;
visibility: hidden;
z-index:2;
}
If someone would be willing to fix the code or atleast tell me what is wrong that would be nice. There is probably a simple solution to this but I again, can't seem to find it.
For those who like to see the code in action, here is the fiddle.
Thank you.
One quick fix is to add some negative margin-top to the elements that create the bubble element(.locations-menu-content and .arrow):
.button {
font-family: "Trebuchet MS";
font-size: 14px;
text-decoration: none;
color: #3D3D3D;
}
.arrow {
top: 140%;
background-color: #648FBD;
position: absolute;
height: 50%;
width: 30%;
opacity: 0;
visibility: hidden;
-ms-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
margin-top: -40px;
}
.locations-menu {
position: absolute;
display: inline-block;
height: 50px;
top: 3%;
left: 30%;
}
.locations-menu:before {
content: "Locations";
font-family: "Trebuchet MS";
font-size: 24px;
}
.locations-menu:focus {
pointer-events: none;
}
.locations-menu:hover .arrow {
opacity: 1;
transition: visibility 2s;
visibility: visible;
pointer-events: auto;
}
.locations-menu-content:hover .locations-menu-content {
opacity: 1;
visibility: visible;
pointer-events: auto;
}
.locations-menu:hover .locations-menu-content {
opacity: 1;
transition: visibility 2s;
visibility: visible;
pointer-events: auto;
}
.locations-menu-content {
background-color: #648FBD;
top: 125%;
left: -15%;
position: absolute;
z-index: 1;
width: 200%;
height: 200%;
text-decoration: none;
opacity: 0;
visibility: hidden;
z-index: 2;
margin-top: -24px;
}
<div tabindex="0" class="locations-menu" id="home-menu">
<div class="arrow"></div>
<ul class="locations-menu-content" id="locations-header">
<br> <a class="button" href="location1.html">Location #1</a>
<br> <a class="button" href="location2.html">Location #2</a>
<br> <a class="button" href="location3.html">Location #3</a>
<br>
</ul>
</div>
</div>
You can just wrap your content in a container and set height: 100%. That way the hover action takes the entire height but the content is positioned where you want it.
HTML
<div tabindex="0" class="locations-menu" id="home-menu">
<div class="wrapper">
<div class="arrow"></div>
<ul class="locations-menu-content" id="locations-header">
<br/>
<a class="button" href="location1.html">Location #1</a><br/>
<a class="button" href="location2.html">Location #2</a><br/>
<a class="button" href="location3.html">Location #3</a><br/>
</ul>
</div>
</div>
CSS
.wrapper{
height: 100%;
}
FIDDLE

animating pseudo element when passing to another element

I got a pseudo-element that marks the user's current choice in a navigation bar. It's a small upward triangle, an icon font from Font-Awesome. here's a jsFiddle DEMO of it (you need to stretch the result panel so everything will be lined).
.subnav > ul > li.active > a:after {
position: relative;
text-align: center;
font-family: FontAwesome;
top: 25px;
right: 50%;
content: "\f0de";
color: #c1c1c1;
}
I've added some basic jQuery function that switches the .active class, and I'm wondering if there's a way to animate the transition of the pseudo element so it'll move horizontally to the new position.
I know pseudo-elements transition are a thing, but searching and googling around I couldn't find anything similar to what I'm looking for. Is this even possible?
In this solution I used the :target pseudo class to switch states, but I recommend you stick with the jQuery function that switches the .active class.
FIDDLE
Markup
<div class="page" id="one">page one</div>
<div class="page" id="two">page two</div>
<div class="page" id="three">page three</div>
<div class="top">
<div class="arrow"></div>
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
</div>
CSS
.top
{
background: #eee;
position:relative;
overflow: hidden;
}
.arrow
{
border-bottom: 1px solid #c2c2c2;
height: 50px;
}
.arrow:before
{
content: '';
display: block;
width: 14px;
height: 14px;
border: 1px solid #c2c2c2;
border-radius: 3px;
position:absolute;
bottom:-9px;
left: 30px;
background: #fff;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
-webkit-transition: left, 0.5s;
-moz-transition: left, 0.5s;
-o-transition: left, 0.5s;
transition: left, 0.5s;
}
ul
{
position: absolute;
top: 0;
list-style: none;
padding-left: 20px;
margin-top: 15px;
}
li
{
display: inline-block;
text-decoration: none;
font-size: 18px;
color: #676767;
margin-right: 40px;
}
.page
{
width: 100%;
height: 200px;
position: absolute;
top: 80px;
opacity: 0;
background: yellow;
-webkit-transition: opacity, 0.5s;
-moz-transition: opacity, 0.5s;
-o-transition: opacity, 0.5s;
transition: opacity, 0.5s;
}
.page:target
{
opacity: 1;
}
#two
{
background: pink;
}
#three
{
background: brown;
}
#one:target ~ .top .arrow:before
{
left: 30px;
}
#two:target ~ .top .arrow:before
{
left: 105px;
}
#three:target ~ .top .arrow:before
{
left: 189px;
}

Resources