wrigamer
wrigamer

Reputation: 19

Display the ::after pseudo-element outside padding space and horizontally center

I try to add a little triangle as the current page indicator under the list item of my navbar with class "active" using ::after.

However,

  1. The alignment of the triangle may not be center for all list items due to the length differences.

    Triangle is not center to the element

  2. The website should be responsive. When I resize the window screen, list items are compacted and enlarge the width of the list. Again, due to the length differences of list items, part of the triangle will be covered if it is under a short list item as the "::after" ignores the padding space.

    Small triangle for short list item when resizing the screen

Here's the code snippet:

nav {
  display: block;
}

ul {
  display: table;
  text-align: center;
  background-color: red;
  margin-bottom: 5%;
  width: 100%;
  padding-left: 0;
  margin-bottom: 0;
  list-style: none;
}

li {
  display: table-cell;
  float: none;
  padding: 5px 0;
  vertical-align: middle;
  position: relative
}

li.active::after {
  content: "";
  width: 0;
  height: 0;
  position: absolute;
  right: 40%;
  border-style: solid;
  border-width: 15px 10px 0 10px;
  border-color: red transparent transparent transparent;
}
<nav>
  <ul>
    <li>xxxxxxxxxxxxxxxxxx</li>
    <li>xxxx</li>
    <li>xxxx</li>
    <li class="active">xxxx</li>
    <li>xxxx</li>
    <li>xxxx</li>
    <li>xxxx</li>
  </ul>
</nav>

Is there any solution for that?

Upvotes: 1

Views: 1138

Answers (2)

Tom
Tom

Reputation: 4292

You're almost there.

You can solve the horizontal position issue by using calc() in your CSS. It's worth looking at the CanIUse data for this to check its support.

You can use this by to calculate the position of your arrow given the fact you want it to be in the centre by subtracting half of the width of your arrow from 50%;

left: calc(50% - 10px)

Then, you just need a negative position on your bottom position attribute to bring the arrow underneath your list element.

bottom: -15px;

Here's a working code snippet;

nav{
    display: block;
}

ul{
    display: table;
    text-align: center;
    background-color: red;
    margin-bottom: 5%;
    width: 100%;
    padding-left: 0;
    margin-bottom: 0;
    list-style: none;
}

li{    
    display: table-cell;
    float: none;
    padding: 5px 0;
    vertical-align: middle;
    position: relative
}

li.active::after{
      content: "";
      width: 0;
      height: 0;
      position: absolute;
      left: calc(50% - 10px);
      bottom: -15px;
      border-style: solid;
      border-width: 15px 10px 0 10px;
      border-color: red transparent transparent transparent;
}
<nav>
<ul>
<li>xxxxxxxxxxxxxxxxxx</li>
<li>xxxx</li> 
<li>xxxx</li> 
<li class="active">xxxx</li> 
<li>xxxx</li> 
<li>xxxx</li> 
<li>xxxx</li> 
</ul>
</nav>

Upvotes: 1

kukkuz
kukkuz

Reputation: 42352

Replace right: 40% in li.active:after with this:

bottom: 0; /* aligns to the bottom*/
right: 50%;
transform: translate(50%, 100%); /* centering */

See demo below:

nav {
  display: block;
}

ul {
  display: table;
  text-align: center;
  background-color: red;
  margin-bottom: 5%;
  width: 100%;
  padding-left: 0;
  margin-bottom: 0;
  list-style: none;
}

li {
  display: table-cell;
  float: none;
  padding: 5px 0;
  vertical-align: middle;
  position: relative
}

li.active::after {
  content: "";
  width: 0;
  height: 0;
  position: absolute;
  bottom: 0;
  transform: translate(50%, 100%);
  right: 50%;
  border-style: solid;
  border-width: 15px 10px 0 10px;
  border-color: red transparent transparent transparent;
}
<nav>
  <ul>
    <li>xxxxxxxxxxxxxxxxxx</li>
    <li>xxxx</li>
    <li>xxxx</li>
    <li class="active">xxxx</li>
    <li>xxxx</li>
    <li>xxxx</li>
    <li>xxxx</li>
  </ul>
</nav>

Upvotes: 1

Related Questions