Search code examples
htmlcssflexboxpseudo-element

CSS ::Before is breaking the line


I am not very experienced in CSS, I searched on the web and I couldn't find a solution for this problem. For some reason, the ::before and text are not staying in the same line. I have another template and it works fine.

I tried "white-space: nowrap" but it doesn't work. I changed to inline-block display, it works, but it changes all the spacing from Flex. I am trying to understand why this happened, and why the same code is causing different effects. I am following a tutorial on YouTube and I copy the code step by step, but the result is not the same.
My page:
enter image description here
His page:
enter image description here

.container {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  margin: 1.5rem;
}

ul {
  display: flex;
  flex-direction: column;
  flex: 3 0;
  justify-content: space-evenly;
  border: 1px solid #ffbbbb;
  border-radius: 1rem;
  list-style-type: none;
  margin: .5rem;
  padding: 0;
}

ul li {
  display: flex;
  justify-content: space-around;
  align-items: center;
  flex-wrap: wrap;
  border-bottom: 1px solid #e4e4e4;
}

ul li:last-child {
  border: none;
}

ul li img {
  width: 5rem;
  height: 5rem;
  border-radius: 100rem;
  object-fit: cover;
}

ul li div {
  padding: 5px;
}

ul li div:not(:first-child) {
  flex-basis: 18%;
}

ul li select {
  width: 3rem;
  outline: none;
  border: none;
  border-bottom: 1px solid lightgrey;
  font-weight: 100;
}

ul .remove-button {
  border-radius: 1rem;
  border: none;
  padding: .5rem;
  color: var(--primary-color);
  opacity: .7;
  outline: none;
}

ul .remove-button:hover {
  opacity: 1;
  cursor: pointer;
}

.checkout {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
  flex: 1 3;
  height: 20rem;
  border: 1px solid #ffbbbb;
  border-radius: 1rem;
  padding: .5rem;
  margin: .5rem;
}

.checkout>div {
  font-size: 1.4rem;
  margin: 1rem;
  flex: 3;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
}

.checkout .foods-count {
  margin-bottom: 1.5rem;
}

.checkout .foods-count::before {
  content: 'Count: ';
  color: grey;
}

.checkout .total-price::before {
  content: 'Price: ';
  color: grey;
}
<div class="container">
  <ul>
    <li *ngFor="let cartItem of cart.items">
      <div>
        <img [src]="cartItem.food.imageUrl" [alt]="cartItem.food.name" />
      </div>
      <div>
        <a [routerLink]="['/food/', cartItem.food.id]">
          {{ cartItem.food.name }}
        </a>
      </div>
      <div>
        <select #quantitySelect (change)="changeQuantity(cartItem, quantitySelect.value)">
          <option>1</option>
          <option>2</option>
          <option>3</option>
          <option>4</option>
          <option>5</option>
        </select>
      </div>
      <div>
        {{ cartItem.price | currency }}
      </div>
      <div>
        <button class="remove-button" (click)="removeFromCart(cartItem)">
          Remove
        </button>
      </div>
    </li>
  </ul>

  <div class="checkout">
    <div class="foods-count">
      {{ cart.items.length }}
    </div>
    <div class="total-price">
      {{ cart.totalPrice | currency }}
    </div>
  </div>
</div>


Solution

  • Turns out, that flex-direction:column also affects ::befores (and ::afters). Remove that, and... Well, now there isn't a space between the ::before and the element. This can be fixed by adding a no-break space \00a0 at the end of the ::before's content.

    Here's the correct code:

    /* ... */
    .checkout>div {
      /* ... */
      flex-direction: row;
      /* ... */
    }
    /* ... */
    .checkout .foods-count::before { content: 'Count:\00a0' }
    .checkout .total-price::before { content: 'Price:\00a0' }
    .checkout :is(.foods-count, .total-price)::before { 
      display: inline;
      color: gray;
    }
    

    The :is( is just a shorthand for both of the ::befores.

    And here's the full snippet:

    .container {
      display: flex;
      flex-wrap: wrap;
      align-items: flex-start;
      margin: 1.5rem;
    }
    
    ul {
      display: flex;
      flex-direction: column;
      flex: 3 0;
      justify-content: space-evenly;
      border: 1px solid #ffbbbb;
      border-radius: 1rem;
      list-style-type: none;
      margin: .5rem;
      padding: 0;
    }
    
    ul li {
      display: flex;
      justify-content: space-around;
      align-items: center;
      flex-wrap: wrap;
      border-bottom: 1px solid #e4e4e4;
    }
    
    ul li:last-child {
      border: none;
    }
    
    ul li img {
      width: 5rem;
      height: 5rem;
      border-radius: 100rem;
      object-fit: cover;
    }
    
    ul li div {
      padding: 5px;
    }
    
    ul li div:not(:first-child) {
      flex-basis: 18%;
    }
    
    ul li select {
      width: 3rem;
      outline: none;
      border: none;
      border-bottom: 1px solid lightgrey;
      font-weight: 100;
    }
    
    ul .remove-button {
      border-radius: 1rem;
      border: none;
      padding: .5rem;
      color: var(--primary-color);
      opacity: .7;
      outline: none;
    }
    
    ul .remove-button:hover {
      opacity: 1;
      cursor: pointer;
    }
    
    .checkout {
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      align-items: center;
      flex: 1 3;
      height: 20rem;
      border: 1px solid #ffbbbb;
      border-radius: 1rem;
      padding: .5rem;
      margin: .5rem;
    }
    
    .checkout>div {
      font-size: 1.4rem;
      margin: 1rem;
      flex: 3;
      display: flex;
      flex-direction: row;
      justify-content: center;
      align-items: flex-start;
    }
    
    .checkout .foods-count {
      margin-bottom: 1.5rem;
    }
    
    .checkout .foods-count::before { content: 'Count:\00a0 ' }
    .checkout .total-price::before { content: 'Price:\00a0 ' }
    .checkout :is(.foods-count, .total-price)::before {
      display: inline;
      color: gray;
    }
    <div class="container">
      <ul>
        <li *ngFor="let cartItem of cart.items">
          <div>
            <img [src]="cartItem.food.imageUrl" [alt]="cartItem.food.name" />
          </div>
          <div>
            <a [routerLink]="['/food/', cartItem.food.id]">
              {{ cartItem.food.name }}
            </a>
          </div>
          <div>
            <select #quantitySelect (change)="changeQuantity(cartItem, quantitySelect.value)">
              <option>1</option>
              <option>2</option>
              <option>3</option>
              <option>4</option>
              <option>5</option>
            </select>
          </div>
          <div>
            {{ cartItem.price | currency }}
          </div>
          <div>
            <button class="remove-button" (click)="removeFromCart(cartItem)">
              Remove
            </button>
          </div>
        </li>
      </ul>
    
      <div class="checkout">
        <div class="foods-count">
          2
        </div>
        <div class="total-price">
          $4
        </div>
      </div>
    </div>