2

I am trying to distribute elements with equal spacing in between while keeping the first and last items left- and right-aligned.

I believe flex-based layouts have an easy solution for it but I want to support older browsers, too.

I have already made a JS-based solution which I will be posting but feel free to suggest better solutions & if it's possible via only CSS.

enter image description here

Here is a fiddle.

ul {
  position: relative;
  margin: 0;
  font-size: 0;
  padding: 0;
  display: table;
  width: 100%;
  list-style: none;
}

ul:after {
  content: '';
  display: block;
  position: absolute;
  top: 50%;
  background: #000;
  left: 0;
  height: 1px;
  width: 100%;
  z-index: -1;
}

li {
  display: table-cell;
  text-align: center;
}

li:first-child {
  text-align: left;
}

li:last-child {
  text-align: right;
}

span {
  font-family: sans-serif;
  display: inline-block;
  font-size: 15px;
  line-height: 1em;
  color: #fff;
  background: #000;
  padding: 6px 9.34px;
  border-radius: 999px;
}
<ul>
  <li><span>1</span></li>
  <li><span>2</span></li>
  <li><span>3</span></li>
  <li><span>4</span></li>
  <li><span>5</span></li>
</ul>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Imran Bughio
  • 4,811
  • 2
  • 30
  • 53

3 Answers3

2

Here's a flex-based solution for people finding this post via search.

See below for browser support data.

ul {
  display: flex;
  justify-content: space-between;
  position: relative;
  margin: 0;
  font-size: 0;
  padding: 0;
  list-style: none;
}

ul:after {
  content: '';
  position: absolute;
  width: 100%;
  top: 50%;
  background-color: #000;
  height: 1px;
  z-index: -1;
}

span {
  font-family: sans-serif;
  display: inline-block;
  font-size: 15px;
  line-height: 1em;
  color: #fff;
  background: #000;
  padding: 6px 9.34px;
  border-radius: 50%;
}
<ul>
  <li><span>1</span></li>
  <li><span>2</span></li>
  <li><span>3</span></li>
  <li><span>4</span></li>
  <li><span>5</span></li>
</ul>

Browser support: Flexbox is supported by all major browsers, except IE < 10. Some recent browser versions, such as Safari 8 and IE10, require vendor prefixes. For a quick way to add prefixes use Autoprefixer. More details in this answer.

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
1

enter image description here

I have used a javascript based solution which does this:

  1. Counts the number of items (5)
  2. Excludes first and last item (5-2=3)
  3. Counts them (3) as double (3*2=6)
  4. Adds the first & last back (6+2=8)
  5. Now gets a percentage division (100/8=12.5%)
  6. Then gives that percentage based amount of total width to first and last element & rest get twice (12.5*2=25%) of that.

[1 = 12.5%] [2 = 25%] [3 = 25%] [4 = 25%] [5 = 12.5%] = 100%

You can view the fiddle here.

<div class="wrap">
  <ul class="js-equal-dist">
    <li><span>1</span></li>
    <li><span>2</span></li>
    <li><span>3</span></li>
    <li><span>4</span></li>
    <li><span>5</span></li>
  </ul>
</div>

CSS

.wrap{
  padding: 0 14px;
}
ul {
  position: relative;
  margin: 0;
  font-size: 0;
  padding: 0;
  display: table;
  width: 100%;
  list-style: none;
}

ul:after {
  content: '';
  display: block;
  position: absolute;
  top: 50%;
  background: #000;
  left: 0;
  height: 1px;
  width: 100%;
  z-index: -1;
}

li {
  display: table-cell;
  text-align: center;
}

li:first-child {
  text-align: left;
}

li:last-child {
  text-align: right;
}

li:first-child span {
  transform: translateX(-50%);
}
li:last-child span {
  transform: translateX(50%);
}

span {
  font-family: sans-serif;
  display: inline-block;
  font-size: 15px;
  line-height: 1em;
  color: #fff;
  background: #000;
  padding: 6px 9.34px;
  border-radius: 999px;
}

JS

  // js-equal-dist
  var totalWidth = $('.js-equal-dist').outerWidth();
  var itemsLength = $('.js-equal-dist li').length;

  var percUnit = 100 / (((itemsLength - 2) * 2) + 2);
  percUnit = percUnit / 100 * totalWidth;

  $('.js-equal-dist li:not(:first-child):not(:last-child)').width(percUnit * 2);
  $('.js-equal-dist li:first-child(), .js-equal-dist li:last-Child()').width(percUnit);

Note that I had to add a wrap div with padding that of half of element & translated first and last element to offset 50% in order to truly be center.

Imran Bughio
  • 4,811
  • 2
  • 30
  • 53
1

CSS

 div {
      width: 500px;
      background-color: black;
      font-size: 0;
    }

    span {
      color: black;
      width: 20px;
      height: 20px;
      display: inline-block;
      background-color: red;
      font-size: 15px;
      margin: 0 calc( ( 500px - 8 * 20px ) / ( 8 + ( 8 - 2 ) ) ); // 8 -> count of elements
    }

    span:first-child {
      margin-left: 0;
    }

    span:last-child {
      margin-right: 0;
    }

HTML

<div>
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>5</span>
<span>6</span>
<span>7</span>
<span>8</span>
</div>

https://codepen.io/N11/pen/MvzeGM

Alexander
  • 26
  • 2