4

How do you center align the first and last flex items in a scrollable horizontal flex container?

Getting scroll to work is easy.

My container has:

scroll-snap-type: x mandatory;
overflow-x: scroll;

and items have:

scroll-snap-align: center;

Scrolling works, however the leftmost and rightmost items in the list are always align to the left and right, respectively.

I would like to get the first and the last items to be able to centered as well in list of scrollable elements.

If we look at this example "home" tab is the left most item. I would like to get that centered with in the scrollable area.

Do I need to have blank tabs on the left and right of the scrollable area ?

Thanks for any advice.

div.scrollmenu {
  background-color: #333;
  overflow: auto;
  white-space: nowrap;
}

div.scrollmenu a {
  display: inline-block;
  color: white;
  text-align: center;
  padding: 14px;
  text-decoration: none;
}

div.scrollmenu a:hover {
  background-color: #777;
}
<div class="scrollmenu">
  <a href="#home">Home</a>
  <a href="#news">News</a>
  <a href="#contact">Contact</a>
  <a href="#about">About</a>
  <a href="#support">Support</a>
  <a href="#blog">Blog</a>
  <a href="#tools">Tools</a>
  <a href="#base">Base</a>
  <a href="#custom">Custom</a>
  <a href="#more">More</a>
  <a href="#logo">Logo</a>
  <a href="#friends">Friends</a>
  <a href="#partners">Partners</a>
  <a href="#people">People</a>
  <a href="#work">Work</a>
</div>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Evren Bingøl
  • 1,306
  • 1
  • 20
  • 32

2 Answers2

1

Do I need to have blank tabs on the left and right of the scrollable area?

That's not a bad idea.

You could create a bunch of "fake" elements on both ends, then give them visibility: hidden.

div.scrollmenu {
  background-color: #333;
  overflow: auto;
  white-space: nowrap;
}

div.scrollmenu a {
  display: inline-block;
  color: white;
  text-align: center;
  padding: 14px;
  text-decoration: none;
}

div.scrollmenu a:hover {
  background-color: #777;
}

/* NEW */
a:nth-child(-n + 5),
a:nth-last-child(-n + 5) {
  background-color: green;
  visibility: hidden;
<div class="scrollmenu">
  <a href="#home">Home</a>
  <a href="#home">Home</a>
  <a href="#home">Home</a>
  <a href="#home">Home</a>
  <a href="#home">Home</a>
  <a href="#home">Home</a>
  <a href="#news">News</a>
  <a href="#contact">Contact</a>
  <a href="#about">About</a>
  <a href="#support">Support</a>
  <a href="#blog">Blog</a>
  <a href="#tools">Tools</a>
  <a href="#base">Base</a>
  <a href="#custom">Custom</a>
  <a href="#more">More</a>
  <a href="#logo">Logo</a>
  <a href="#friends">Friends</a>
  <a href="#partners">Partners</a>
  <a href="#people">People</a>
  <a href="#work">Work</a>
  <a href="#home">Home</a>
  <a href="#home">Home</a>
  <a href="#home">Home</a>
  <a href="#home">Home</a>
  <a href="#home">Home</a>
  <a href="#home">Home</a>
</div>

However, there's a simpler and more semantically valuable solution: use CSS pseudo-elements.

Since you're only focusing on the appearance of the layout, you shouldn't tamper with the HTML. You should stick with pure CSS.

And since pseudo-elements on a flex container are treated as flex items, you can use ::before (the first item in the natural flow) and ::after (the last item in the natural flow) to create the centering effect you need.

div.scrollmenu {
  background-color: #333;
  overflow: auto;
  white-space: nowrap;
  display: flex;
}

div.scrollmenu a {
  color: white;
  text-align: center;
  padding: 14px;
  text-decoration: none;
}

div.scrollmenu a:hover {
  background-color: #777;
}

/* NEW */
.scrollmenu::before,
.scrollmenu::after {
  content: "";
  flex: 0 0 50%;
}
<div class="scrollmenu">
  <a href="#home">Home</a>
  <a href="#news">News</a>
  <a href="#contact">Contact</a>
  <a href="#about">About</a>
  <a href="#support">Support</a>
  <a href="#blog">Blog</a>
  <a href="#tools">Tools</a>
  <a href="#base">Base</a>
  <a href="#custom">Custom</a>
  <a href="#more">More</a>
  <a href="#logo">Logo</a>
  <a href="#friends">Friends</a>
  <a href="#partners">Partners</a>
  <a href="#people">People</a>
  <a href="#work">Work</a>
</div>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
0

I got this to work with using transform3D. I put all the content in a flex container and scrolled the whole container using transform3D plus some javascript. I calculate the screen size and got the center of the screen and did some math and calculate the width of each item in the container and knowing each items index gave me an offset which I did then did animation to scroll the content left or right with transform3d.

Evren Bingøl
  • 1,306
  • 1
  • 20
  • 32