Salem
Salem

Reputation: 17

Anchor tag underline is not aligning under text with highlight animation

I'm trying to have my anchor tag perform an animation where the underline highlights the text above upon hovering over it. Not sure why the underline is so far over to the left. Any ideas on what might be causing the issue?

I've tried changing the container class to be position: absolute and then set the content within as relative, but that didn't work either.

.section-title {
  display: block;
  font-size: 2em;
  text-align: center;
  padding-bottom: 1.5%;
  font-size: 2em;
  transform: translateX(0%) translateY(-25%);
  /* z-index: -1; */
}

.section-title-highlight {
  color: black;
}

.section-title-highlight:before {
  content: '';
  display: block;
  height: 20px;
  width: 20%;
  background: #35FCCE;
  position: absolute;
  bottom: 0;
  left: 0;
  transition: height .7s;
  z-index: -1;
}

.section-title-highlight:hover:before {
  height: 85%;
}

a {
  text-decoration: none;
  cursor: default;
  display: block;
}

.container {
  padding-top: 3%;
  padding-left: 5%;
  padding-right: 5%;
  padding-bottom: 7%;
  margin-top: 0;
  margin-left: 5%;
  margin-right: 5%;
  margin-bottom: 5%;
  display: flex;
  flex-direction: column;
  align-items: center;
  height: 100%;
  background-color: rgb(236, 236, 236);
}

.container-item {
  display: flex;
  flex-direction: column;
}

#home {
  height: 500px;
  /* margin-bottom: 0; */
  position: relative;
}

#projects {
  height: 600px;
  position: relative;
}
<div class="container">
  <div id="projects">
    <a href="#" class="section-title-highlight section-title">Projects</a>
    <div class="container-item">
      <p>
        asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf
      </p>
    </div>
  </div>

Upvotes: 0

Views: 613

Answers (3)

haelmic
haelmic

Reputation: 610

All you need to do is not use your relative for anything other than the title and you'll be fine!

This uses the original code from the question and changes the width of the box shrinks the hight, and adds a margin-bottom transition.

    .section-title {
      display: block;
      font-size: 2em;
      text-align: center;
      padding-bottom: 1.5%;
      font-size: 2em;
      transform: translateX(0%) translateY(-25%);
      /* z-index: -1; */
    }

    .section-title-highlight {
      color: black;
    }

    .section-title-highlight:before {
      content: '';
      display: block;
      height: 5px;
      width: 100%;
      background: #35FCCE;
      position: absolute;
      margin-bottom: .2em;
      bottom: 0;
      left: 0;
      transition: margin-bottom .5s , height .7s;
      z-index: -1;
    }

    .section-title-highlight:hover:before {
      height: 85%;
      margin-bottom:0;
    }

    a {
      text-decoration: none;
      cursor: default;
      display: block;
    }

    .container {
      padding-top: 3%;
      padding-left: 5%;
      padding-right: 5%;
      padding-bottom: 7%;
      margin-top: 0;
      margin-left: 5%;
      margin-right: 5%;
      margin-bottom: 5%;
      display: flex;
      flex-direction: column;
      align-items: center;
      height: 100%;
      background-color: rgb(236, 236, 236);
    }

    .container-item {
      display: flex;
      flex-direction: column;
    }

    #home {
      height: 500px;
      /* margin-bottom: 0; */
      position: relative;
    }

    #projects {
      height: 2em;
      position: relative;
    }
    <div class="container">
      <div id="projects">
        <a href="#" class="section-title-highlight section-title">Projects</a>
        <div class="container-item">
        </div>
      </div>
      <p>
            asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf
          </p>

Upvotes: 0

BobRodes
BobRodes

Reputation: 6165

I got the result I believe you are looking for simply by changing this:

.section-title-highlight:before {
  width: 20%;
}

to this:

.section-title-highlight:before {
  width: 100%;
}

The discussion about "faking the text width" boils down to this: your div.projects width is determined by the width of your text. Your a::before width is determined by the width of div.project. Ergo, setting a::before's width property to 100% sets it to the width of your text.

It is also necessary, as you have surmised, to absolutely position the a::before element. If you don't, it will be in the flow, take up 100% of its container, and then wrap your text onto the next row. If you try removing position: absolute from it this will be apparent to you.

Changing the container class to absolute and the element to relative only absolutely positions your container in the next element above it in the DOM tree (the "containership hierarchy," if that makes more sense) that is positioned relatively. So no, that wouldn't work.

Here's the code:

    .section-title {
      display: inline-block;
      font-size: 2em;
      text-align: center;
      padding-bottom: 1.5%;
      font-size: 2em;
      transform: translateX(0%) translateY(-25%);
      /* z-index: -1; */
    }

    .section-title-highlight {
      color: black;
    }

    .section-title-highlight:before {
      content: '';
      display: inline-block;
      height: 20px;
      width: 100%;
      background: #35FCCE;
      position: absolute;
      bottom: 0;
      left: 0;
      transition: height .7s;
      z-index: -1;
    }

    .section-title-highlight:hover:before {
      height: 85%;
    }

    a {
      text-decoration: none;
      cursor: default;
    }

    .container {
      padding: 3% 5% 7%;
      margin: 0 5% 5%;
      display: flex;
      flex-direction: column;
      align-items: center;
      background-color: rgb(236, 236, 236);
    }

    .container-item {
      display: flex;
      flex-direction: column;
    }

    #projects {
      height: 600px;
      position: relative;
    }  

    .projects-header {
      text-align: center;
    }
  <div class="container">
    <div id="projects">
      <div class="projects-header">
        <a href="#" class="section-title-highlight section-title">Projects</a>
      </div>
      <div class="container-item">
        <p>
          Edit: the problem was that the highlight on the title would expand to be as wide as this paragraph, which was not apparent when only "asdf" was in it..
        </p>
      </div>
    </div>
  </div>

Maybe a little clarification on position will be helpful. Default value for position is static. Statically positioned elements are placed wherever they occur in the page flow, as if they were paragraphs of text. A relatively positioned element is positioned relative to its static position, where top and left are offsets from the static position. So, if, say, you gave your div.projects a top: -10px, it would be positioned 10px higher than it would be if you didn't have any position value specified (i.e. the position type was static).

Absolutely positioned elements are positioned inside a relatively-positioned container, at top: 0 and left: 0 unless otherwise specified. So, it isn't strictly necessary for you to have a top: 0 in your a::before style. You do have to have the bottom: 0, since otherwise your bar would be at the top of your text instead of the bottom.

Edit

The fix (well, my fix) for the problem that the OP and FluffyKitten describe in the comments required two steps.

  1. The structure of the HTML was such that the anchor element was being treated as a flex cell. As such, its width was tied to the width of the paragraph. So, the first step is to wrap the anchor tag in a div. (Done as div.project-header.)
  2. The anchor tag was in block display, meaning it takes up the entire width of its container. The fix to this was to change display:block in the .section-title style to display: inline-block.

Upvotes: 1

FluffyKitten
FluffyKitten

Reputation: 14312

You are using position:absolute on your highlight block, with places it in the exact position you specify, relative to it's parent container that has position:relative.

Your highlight should be relative to the text in the section-title-highlight, so you simply need to make it relative like this:

.section-title-highlight {
  position:relative;
}

Your highlight element is now being placed at the bottom left of the text:

.section-title-highlight:before {
  height: 2px;      /* or whatever your starting height should be */
  width: 100%;
  position: absolute;
  bottom: 0;
  left: 0;
  /* rest of your css here... */ 
}

The other problem you have is that the highlight is appearing much wider than the text. This is because your title is a block element so it stretches the full width of its container.

You can fix that by making the highlight an inline or inline-block element. In the example below I have made your section-title a block element and left your section-title-highlight inline:

 <div class="section-title">
     <a class="section-title-highlight">Projects</a>
 </div>

Working example:

.section-title {
  display: block;
  text-align: center;
  padding-bottom: 1.5%;
  font-size: 2em;
  transform: translateX(0%) translateY(-25%);
  /* z-index: 0; */
}

.section-title-highlight {
  position: relative;
  color: black;
}

.section-title-highlight:before {
  content: '';
  display: block;
  height: 2px;  /* or whatever height you want to start */
  width: 100%;
  background: #35FCCE;
  position: absolute;
  bottom: 0;
  left: 0;
  transition: height .7s;
  z-index: -1;
}

.section-title-highlight:hover:before {
  height: 85%;
}

a {
  text-decoration: none;
  cursor: default;
  display: block;
}

.container {
  padding-top: 3%;
  padding-left: 5%;
  padding-right: 5%;
  padding-bottom: 7%;
  margin-top: 0;
  margin-left: 5%;
  margin-right: 5%;
  margin-bottom: 5%;
  display: flex;
  flex-direction: column;
  align-items: center;
  height: 100%;
  background-color: rgb(236, 236, 236);
}

.container-item {
  display: flex;
  flex-direction: column;
}

#home {
  height: 500px;
  /* margin-bottom: 0; */
  position: relative;
}

#projects {
  height: 600px;
  position: relative;
}
<div class="container">
  <div id="projects">

    <a href="#" class="section-title-highlight section-title">Projects</a>
      <p>The heading above is using a block display (as in your code), so it is appearing the full width of the container.</p>
    <div class="section-title">
      <span class="section-title-highlight">Projects</span>
    </div>
    <div class="container-item">
      <p>
        This heading is using an inline element so the highlight is only the width of the text
      </p>
    </div>
  </div>
</div>

Upvotes: 1

Related Questions