5

(I'm quite new in web-design) I have a list of links (sections on current page) that can extend to multiple lines depending on viewport size. Links are separated by a vertical line (border-left):

Current results

I want to avoid the border to be displayed for first element of each line. I've managed to avoid it for the the first child but I can't figure out how to do it for the first element of each line. Something like:

Expected results

Note that this list is probably different for each page.

Question: How to achieve such effect? CSS? JavaScript?

.links a {
  display: inline-block;
}
.links a:not(:first-child) {
  border-left: 1px solid black;
  padding-left: 15px;
}
.links a:not(:last-child) {
  padding-right: 15px;
}
<div class="links">
  <a href="#">Link number 1</a>
  <a href="#">Link number 2</a>
  <a href="#">Link number 3</a>
  <a href="#">Link number 4</a>
  <a href="#">Link number 567</a>
  <a href="#">Link number 6</a>
  <a href="#">Link number 7</a>
  <a href="#">Link number 8</a>
  <a href="#">Link number 9</a>
</div>

PS: the display: inline-block is just to avoid wrapping between lines. I'd like to avoid changing the HTML structure since many pages are affected. Such links are always nested in a <div class="links"></div> as shown in the example.

cbuchart
  • 10,847
  • 9
  • 53
  • 93
  • You would need media queries. There is no way to do this dynamically with CSS. It has no idea when items wrap. – Paulie_D Oct 01 '18 at 16:28
  • Oh... so, what if pages have different set of links? one specific CSS for each one? I'll update the question to be clear about it... may be some JS? – cbuchart Oct 01 '18 at 16:30
  • That would probably be the only way. – Paulie_D Oct 01 '18 at 16:30
  • Your dynamic list is a list of words, so only way I imagine as *the best* from performance perspective is to get an avarage widht of a symbol (number, letter) and calculate `@media queries` in CSS on those sizes – Julius Dzidzevičius Oct 01 '18 at 16:47
  • 1
    @Paulie_D *"There is no way to do this dynamically with CSS."* while the "dynamically" portion holds true, OP's specific request is possible with CSS only. Though my answer could be considered a workaround, I suppose. – Tyler Roper Oct 01 '18 at 16:56

3 Answers3

1

Set overflow: hidden; on the container and give your links a negative left-margin. You can counteract the negative margin on the other links by simply doubling the padding-right.

.links {
  overflow: hidden;
}
.links a {
  display: inline-block;
  border-left: 1px solid black;
  padding-left: 15px;
  margin-left: -15px;
}
.links a:not(:last-child) {
  padding-right: 30px;
}
<div class="links">
  <a href="#">Link number 1</a>
  <a href="#">Link number 2</a>
  <a href="#">Link number 3</a>
  <a href="#">Link number 4</a>
  <a href="#">Link number 567</a>
  <a href="#">Link number 6</a>
  <a href="#">Link number 7</a>
  <a href="#">Link number 8</a>
  <a href="#">Link number 9</a>
</div>

How It Works

The left margin and left border are present, however the negative margin forces them out of the container. We then hide anything outside of the container with overflow: hidden.

The example below presents what's actually happening by removing overflow: hidden; and giving the container a border:

.links {
  border: 1px solid red;
  overflow: visible;
  margin-left: 30px;
}
.links a {
  display: inline-block;
  border-left: 1px solid black;
  padding-left: 15px;
  margin-left: -15px;
}
.links a:not(:last-child) {
  padding-right: 30px;
}
<div class="links">
  <a href="#">Link number 1</a>
  <a href="#">Link number 2</a>
  <a href="#">Link number 3</a>
  <a href="#">Link number 4</a>
  <a href="#">Link number 567</a>
  <a href="#">Link number 6</a>
  <a href="#">Link number 7</a>
  <a href="#">Link number 8</a>
  <a href="#">Link number 9</a>
</div>
Tyler Roper
  • 21,445
  • 6
  • 33
  • 56
  • Thanks! it works flawlessly! Could it be modified to work when `.links` has `text-align: center`? It is a change in the design for a subset of pages... should I post it as a separate question or extend this one? – cbuchart Oct 02 '18 at 07:15
  • I managed to solve that particular issue using JS, thanks for your help! – cbuchart Oct 02 '18 at 10:08
1

Here is an easy way where you can use a pseudo element to hide the first borders.

.links {
  overflow: hidden;
  position:relative;
  width:600px;
  animation:change 4s linear infinite alternate;
}
.links:before {
  content:"";
  position:absolute;
  top:0;
  bottom:0;
  left:0;
  width:1px;
  background:#fff;
}
.links a {
  display: inline-block;
  border-left: 1px solid black;
  padding-left: 15px;
}

@keyframes change {
  to{width:160px}
}
<div class="links">
  <a href="#">Link number 1</a>
  <a href="#">Link number 2 5q4d </a>
  <a href="#">Link number 3</a>
  <a href="#">Link number 4</a>
  <a href="#">Link number 567</a>
  <a href="#">Link number 6</a>
  <a href="#">Link number 7 dqsd dqs</a>
  <a href="#">Link number 8</a>
  <a href="#">Link number 9</a>
</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
0

Though I prefer the solutions proposed by Tyler Roper and Temani Afif because they show the correct result from the very first rendering (especially noticeable in pages with many additional resources), I want to share another solution (using JavaScript) inspired in this other answer.

$(document).ready(function() {
  fn = function() {
    var prevTop = -1;
    $("a", $(".links")).each(function() {
      var link = $(this);
      var top = link.offset().top;
      if (top == prevTop) {
        link.attr("class", "border");
      } else { // new line
        prevTop = top;
        link.removeClass("border"); // in case 'border' was previously added
      }
    });
  };
  $(window).resize(fn);
  fn();
});
.links {
  text-align: center;
}

.links a {
  display: inline-block;
  padding-left: 15px;
  padding-right: 15px;
}

.links a.border {
  border-left: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="links">
  <a href="#">Link number 1</a>
  <a href="#">Link number 2</a>
  <a href="#">Link number 3</a>
  <a href="#">Link number 4</a>
  <a href="#">Link number 567</a>
  <a href="#">Link number 6</a>
  <a href="#">Link number 7</a>
  <a href="#">Link number 8</a>
  <a href="#">Link number 90</a>
</div>

As seen, above code manages the case where the links are centered in the screen instead of left-aligned.

Note: As text-centering was not part of my original question (such requirement appeared after I implemented the accepted answer), I'm not considering that for the correctness of the other answers proposed, I'm just publishing this contribution for completeness.

cbuchart
  • 10,847
  • 9
  • 53
  • 93