9

I have an tag which is displayed as a block. On page load, its width is increased by a css animation from zero to some percentage of the containing div (the fiddle contains a MWE, but there is more than one link in this div, each with a different width). On hover, I want it to change colour, change background colour, and also expand to 100% of the div, using a CSS transition. The colour and background colour bit is working, but it seems to ignore the width transition.

Snippet:

.home-bar {
  text-decoration: none;
  background-color: white;
  color: #5e0734;
  display: block;
  -webkit-animation-duration: 1.5s;
  -webkit-animation-timing-function: ease-out;
  -webkit-animation-fill-mode: forwards;
  animation-duration: 1.5s;
  animation-fill-mode: forwards;
  transition: color, background-color, width 0.2s linear;/*WIDTH IGNORED*/
  border: 2px solid #5e0734;
  overflow: hidden;
  white-space: nowrap;
  margin-right: 0;
  margin-left: 5px;
  margin-top: 0;
  margin-bottom: 5px;
  padding: 0;
}

.home-bar:hover {
  background-color: #5e0734;
  color: white;
  width: 100%;/*WIDTH IGNORED*/
  text-decoration: none;
}

#bar0 {
  -webkit-animation-name: grow0;
  animation-name: grow0;
}

@keyframes grow0 {
  from {
    width: 0%;
  }
  to {
    width: 75%;
  }
}
<a href="#" id="bar0" class="home-bar">LINK</a>

Note - I've tested it with changing the height of the link on hover, and it worked. Only the width does not work. Perhaps it has something to do with the animation on page-load.

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
Alex
  • 2,270
  • 3
  • 33
  • 65
  • So you wan't to change/animate the width when you hover the link not on pageload? I'm not sure I understood it correct? – webta.st.ic Apr 30 '18 at 10:52
  • @MrBuggy Sorry, no, I'll make it clearer. There are five links, each of which expands to some percentage of the div (less than 100%) on page load. This works, and is perfect. I then want a **further** transition which expands the width of the link even more (to 100%) during hover. – Alex Apr 30 '18 at 10:54
  • To make it really clear, please put you'r whole code into the snipped and describe what happens, and what should happen... – webta.st.ic Apr 30 '18 at 10:55
  • Apparently the `width:75%` in the animation overrides the `width:100%` in the :hover rule. Not sure why, but you can override this by defining a new animation in the :hover. https://jsfiddle.net/MrLister/s5bopjet/2/ Would that work? – Mr Lister Apr 30 '18 at 11:00
  • 1
    @MrLister Yes, that must be what's happening, but I don't know why. Perhaps because of the `animation-fill-mode: forwards;`? – Alex Apr 30 '18 at 11:01
  • Are you searching for something like this: https://codepen.io/STWebtastic/pen/ervYOM – webta.st.ic Apr 30 '18 at 11:05
  • @MrBuggy Basically, yes, but with the black border growing, rather than fixed at the end – Alex Apr 30 '18 at 11:07

1 Answers1

3

When you set width using animation you will override any other width defined with CSS inluding the one defined by hover. The styles inside a keyframes is more specific than any other styles:

CSS Animations affect computed property values. This effect happens by adding a specified value to the CSS cascade ([CSS3CASCADE]) (at the level for CSS Animations) that will produce the correct computed value for the current state of the animation. As defined in [CSS3CASCADE], animations override all normal rules, but are overridden by !important rules. ref

A workaround is to consider both width/max-width properties to avoid this confusion:

.home-bar {
  text-decoration: none;
  background-color: white;
  color: #5e0734;
  display: block;
  animation: grow0 1.5s forwards;
  transition: color, background-color, max-width 0.2s linear;
  border: 2px solid #5e0734;
  max-width: 75%; /*Set max-wdith*/
}

.home-bar:hover {
  background-color: #5e0734;
  color: white;
  max-width: 100%; /* Update the max-width of hover*/
  text-decoration: none;
}

/*Animate width to 100%*/
@keyframes grow0 {
  from {
    width: 10%;
  }
  to {
    width: 100%;
  }
}
<a href="#" id="bar0" class="home-bar">LINK</a>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • That does seem to be the reason. I've tried adding !important to the transition stuff, but it didn't help. – Alex Apr 30 '18 at 11:07
  • @Alex Then override the animation itself. – Mr Lister Apr 30 '18 at 11:09
  • @TemaniAfif Thanks! Nice workaround, but I've updated the fiddle, and it's not working: https://jsfiddle.net/s5bopjet/3/ The only difference is that I've put the origin max-width in the css for that individual block, rather than the class, as each has a different width. – Alex Apr 30 '18 at 11:30
  • @Alex show me, maybe you forget something ... the width must go to 100% in the animation – Temani Afif Apr 30 '18 at 11:31
  • @TemaniAfif Sorry, I sent my comment half-way through. Fiddle updated – Alex Apr 30 '18 at 11:32
  • @Alex now you issue is with specifity, ID is more specific than class with hover, so the hover won't apply .. here is a workaround to make the hover more specific : https://jsfiddle.net/s5bopjet/4/ – Temani Afif Apr 30 '18 at 11:34
  • @TemaniAfif That works, thank you. Could you explain what `not(#randomid_58)` does? – Alex Apr 30 '18 at 11:36
  • @Alex by addin an ID i make the specifty higher but since I cannot add the same id to all i use not() to say select all without this ID and since no one has this ID it will select all ;) refer to this for more information : https://stackoverflow.com/a/49742059/8620333 – Temani Afif Apr 30 '18 at 11:40
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/170079/discussion-between-alex-and-temani-afif). – Alex Apr 30 '18 at 11:42