2

I have a navigation bar that includes the usual links, and to improve the user experience I have a bottom border show on hover:

enter image description here

I achieve this with the following code:

body {
  background-color: #E9EBEE;
  color: #666666;
  margin: 0px;
  font-family: 'Open Sans', Helvetica, Arial, sans-serif;
  font-size: 16px;
}
.nav {
  padding-top: 50px;
  padding-bottom: 5px;
  margin-top: 2em;
  margin-bottom: 6em;
  background-color: #F6F7F9;
  color: #666666;
  font-size: 1.5em;
  line-height: 1.5;
  text-align: center;
}
.nav > .links {
  margin-top: -36px;
  border-left: solid 1px #E9EBEE;
  font-size: 0.8em;
}
.nav > .links > .link {
  float: left;
  position: inherit;
  border-right: solid 1px #E9EBEE;
  border-bottom-width: 2px;
  width: 8em;
  transition: border-color .2s;
}
.nav > .links > .link:hover {
  border-bottom: solid;
  border-bottom-color: #3B5998;
  border-bottom-width: 2px;
  color: #3B5998;
}
<body>
  <div class="nav">
    <div class="links">
      <div class="link">
        Servers
      </div>
    </div>
  </div>
</body>

I'd like the border to be on the bottom of nav; to do this I added padding-bottom:11px; to .nav > .links > .link, which resulted in this:

enter image description here

The result is exactly what I wanted, however notice that the right and left borders of each navigation item has been extended; something that I should've realised would happen when adding the padding-bottom attribute to .nav > .links > .link.

To fix this I thought that I could use a border-bottom-height since there is a border-bottom-width but apparently no such thing exists, and I don't want to use an additional element if possible to provide the left & right borders. As seen in the first image, the left and right borders should be approximately the height of the text contained.

Is this possible without an additional 'wrapper' element?

Community
  • 1
  • 1
AStopher
  • 4,207
  • 11
  • 50
  • 75

2 Answers2

4

Use a pseudo element instead, i.e. ::after (if to support IE8, use :after, works cross browser)

body {
  background-color: #E9EBEE;
  color: #666666;
  margin: 0px;
  font-family: 'Open Sans', Helvetica, Arial, sans-serif;
  font-size: 16px;
}
.nav {
  padding-top: 50px;
  padding-bottom: 5px;
  margin-top: 2em;
  margin-bottom: 6em;
  background-color: #F6F7F9;
  color: #666666;
  font-size: 1.5em;
  line-height: 1.5;
  text-align: center;
}
.nav > .links {
  margin-top: -36px;
  border-left: solid 1px #E9EBEE;
  font-size: 0.8em;
}
.nav > .links > .link {
  float: left;
  position: relative;
  border-right: solid 1px #E9EBEE;
  border-bottom-width: 2px;
  width: 8em;
  transition: border-color .2s;
}
.nav > .links > .link:hover::after {
  content: '';
  position: absolute;
  top: calc(100% + 11px);
  left: 0;
  width: 100%;
  height: 2px;  
  background: #3B5998;
}
<body>
  <div class="nav">
    <div class="links">
      <div class="link">
        Servers
      </div>
    </div>
  </div>
</body>
Asons
  • 84,923
  • 12
  • 110
  • 165
  • good answer. technically, pseudo-elements should have two colons (`::after`) to distinguish them from pseudo-classes like `:hover`. ([source](http://stackoverflow.com/questions/8069973/what-is-the-difference-between-a-pseudo-class-and-a-pseudo-element-in-css)) – Woodrow Barlow Jun 26 '16 at 17:45
  • @WoodrowBarlow Very correct, though it also says _For compatibility with existing style sheets, user agents must also accept the previous one-colon notation for pseudo-elements introduced in CSS levels 1 and 2 (namely, :first-line, :first-letter, :before and :after)._ – Asons Jun 26 '16 at 17:48
  • @WoodrowBarlow This is me which still has IE8 users, hence need to use the single colon version, ...will make a comment about it in my answer – Asons Jun 26 '16 at 17:55
2

There are many ways to do this. In most cases, the simplest and cleanest option would be to create a pseudo-element (as suggested by LGSon), but sometimes this isn't possible. For example, you may already have used both pseudo-elements for other effects, or you may not be able to position it properly (notice that the pseudo-element method requires you to set the .link element's position property to relative -- this may not always be possible for your layout).

Below is an alternative technique, using box-shadow. It has its own drawbacks, most notably that it only works when working with a solid-color background.

The idea is simple: draw two box-shadows (since they can stack!) on the hovered element. The bottom one is two pixels taller than the top one. The bottom one is blue, the top one is the same color as the nav bar.

body {
  background-color: #E9EBEE;
  color: #666666;
  margin: 0px;
  font-family: 'Open Sans', Helvetica, Arial, sans-serif;
  font-size: 16px;
}
.nav {
  padding-top: 50px;
  padding-bottom: 5px;
  margin-top: 2em;
  margin-bottom: 6em;
  background-color: #F6F7F9;
  color: #666666;
  font-size: 1.5em;
  line-height: 1.5;
  text-align: center;
}
.nav > .links {
  margin-top: -36px;
  border-left: solid 1px #E9EBEE;
  font-size: 0.8em;
}
.nav > .links > .link {
  float: left;
  position: inherit;
  border-right: solid 1px #E9EBEE;
  border-bottom-width: 2px;
  width: 8em;
  transition: border-color .2s;
}
.nav > .links > .link:hover {
  color: #3B5998;
  box-shadow:
    0 11px 0 #F6F7F9,
    0 13px 0 #3B5998;
}
<body>
  <div class="nav">
    <div class="links">
      <div class="link">
        Servers
      </div>
    </div>
  </div>
</body>
Woodrow Barlow
  • 8,477
  • 3
  • 48
  • 86
  • I'm accepting LGSon's answer as I was able to use pseudo elements, however `box-shadow` seems intriguing and is a good alternative. – AStopher Jun 26 '16 at 17:43