Search code examples
htmlcssflexboxcss-gridstyling

Aligning divider element centrally with the repeated elements around it


I need to create a section like this:

enter image description here

Here's what I have already tried:

.container {
  display: flex;
  justify-content: space-between;
}

.content {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.step {
  display: flex;
  flex-direction: row;
  align-items: center;
}

.divider {
  background-color: #d9d9d9;
  border-radius: .2rem;
  height: 2px;
  width: 3rem;
  margin-top: 1.2rem;
  transform: translateY(-50%);
  margin: {
    left: $spacing--22;
    right: $spacing--22;
  }
}
<div class="container">
  <div v-for="(step, index) in steps" :key="index" class="step">
    <div class="content">
      <div class="icon">
        // ICON CONTENT
      </div>
      <h3 class="title">
        // TITLE CONTENT
      </h3>
      <p class="description">
        // DESCRIPTION CONTENT
      </p>
    </div>
    <div v-if="index + 1 < steps.length" class="step-process__divider" />
  </div>
</div>

The problem is that the divider doesn't look like it's always centered between the two step elements.

Is there a better way to achieve this?


Solution

  • I'd prefer you to use CSS-pseudo elements and CSS-selectors, specifically, :not, first-child, last-child, before and after.

    You can use the :not selector to get the child elements that are not first or last, i.e., anything between them, then add lines before and after the component.

    See this working example:

    .container {
      display: flex;
      justify-content: space-between;
    }
    
    .content {
      display: flex;
      align-items: center;
      text-align: center;
    }
    
    .step {
      display: flex;
      flex-direction: row;
      align-items: center;
    }
    
    .divider {
      background-color: #d9d9d9;
      border-radius: .2rem;
      height: 2px;
      width: 3rem;
      margin-top: 1.2rem;
      transform: translateY(-50%);
      margin: {
        left: $spacing--22;
        right: $spacing--22;
      }
    }
    
    .custom-class:not(:first-child):not(:last-child) {
      display: flex;
      align-items: center;
      justify-content: center;
    }
    
    .custom-class:not(:first-child):not(:last-child)::before {
      content: '—';
    }
    
    .custom-class:not(:first-child):not(:last-child)::after {
      content: '—';
    }
    <div class="container">
      <div v-for="(step, index) in steps" :key="index" class="step">
        <div class="content">
          <div class="custom-class icon">
            ICON CONTENT
          </div>
          <h3 class="custom-class title">
            TITLE CONTENT
          </h3>
          <p class="custom-class description">
            DESCRIPTION CONTENT
          </p>
        </div>
        <div v-if="index + 1 < steps.length" class="step-process__divider" />
      </div>
    </div>