takeradi
takeradi

Reputation: 3861

CSS Pseudo elements positioning issue

I am facing an issue with positioning and alignment of pseudo elements. I have pasted the snippet below. Could you please tell me why the elements are overlapping and how to get them to appear next to each other without the overlap?

.switch {
  display: inline-block;
  margin-right: 15px;
}

.switch label {
  position: relative;
  cursor: pointer;
}

.switch input[type="checkbox"] + label::before {
  position: absolute;
  display: inline-block;
  content: '';
  height: 18px;
  width: 33px;
  border: 1px solid gray;
  border-radius: 9px;
  background-color: gray;
  top: 2px;
  right: -50px;
}

.switch input[type="checkbox"]:checked + label::before {
  border: 1px solid red;
  background-color: red;
  right: -50px;
}

.switch input[type="checkbox"] + label::after {
  position: absolute;
  display: inline-block;
  content: '';
  height: 14px;
  width: 14px;
  border: 1px solid white;
  border-radius: 50%;
  background-color: white;
  top: 4px;
  right: -33px;
}

.switch input[type="checkbox"]:checked + label::after {
  right: -48px;
}

.switch input[type="checkbox"] {
  display: none;
}
<div class="switch">
  <input type="checkbox" id="checkbox1">
  <label for="checkbox1">Lorem ipsum Test</label>
</div>
<div class="switch">
  <input type="checkbox" id="checkbox2">
  <label for="checkbox2">Test1</label>
</div>
<div class="switch">
  <input type="checkbox" id="checkbox3">
  <label for="checkbox3">Lorem ipsum Test2</label>
</div>

Upvotes: 1

Views: 59

Answers (2)

Gabriele Petrioli
Gabriele Petrioli

Reputation: 196002

When an element is absolutely positioned it gets out of the normal flow. This means that it does not affect other elements with its dimensions/positioning.

A solution is to take into consideration its dimensions/positioning in the container element (the label in this case)

So giving a padding-right:50px to the label and positioning the pseudo-elements accordingly will fix it.

Updated code

.switch {
  display: inline-block;
  margin-right: 15px;
}

.switch label {
  position: relative;
  cursor: pointer;
  padding-right:50px;
}

.switch input[type="checkbox"] + label::before {
  position: absolute;
  display: inline-block;
  content: '';
  height: 18px;
  width: 33px;
  border: 1px solid gray;
  border-radius: 9px;
  background-color: gray;
  top: 2px;
  right: 0;
}

.switch input[type="checkbox"]:checked + label::before {
  border: 1px solid red;
  background-color: red;
  right: 0;
}

.switch input[type="checkbox"] + label::after {
  position: absolute;
  display: inline-block;
  content: '';
  height: 14px;
  width: 14px;
  border: 1px solid white;
  border-radius: 50%;
  background-color: white;
  top: 4px;
  right: 17px;
}

.switch input[type="checkbox"]:checked + label::after {
  right: 2px;
}

.switch input[type="checkbox"] {
  display: none;
}
<div class="switch">
  <input type="checkbox" id="checkbox1">
  <label for="checkbox1">Lorem ipsum Test</label>
</div>
<div class="switch">
  <input type="checkbox" id="checkbox2">
  <label for="checkbox2">Test1</label>
</div>
<div class="switch">
  <input type="checkbox" id="checkbox3">
  <label for="checkbox3">Lorem ipsum Test2</label>
</div>

Upvotes: 2

Oriol
Oriol

Reputation: 288230

They overlap because position: absolute takes elements out of the normal flow:

In the absolute positioning model, a box is explicitly offset with respect to its containing block. It is removed from the normal flow entirely (it has no impact on later siblings). [...] the contents of an absolutely positioned element do not flow around any other boxes. They may obscure the contents of another box (or be obscured themselves)

You can add some margin to fix that:

.switch label {
  margin-right: 50px;
}

.switch {
  display: inline-block;
  margin-right: 15px;
}
.switch label {
  display: block;
  margin-right: 50px;
  position: relative;
  cursor: pointer;
}
.switch input[type="checkbox"] + label::before {
  position: absolute;
  display: inline-block;
  content: '';
  height: 18px;
  width: 33px;
  border: 1px solid gray;
  border-radius: 9px;
  background-color: gray;
  top: 2px;
  right: -50px;
}
.switch input[type="checkbox"]:checked + label::before {
  border: 1px solid red;
  background-color: red;
  right: -50px;
}
.switch input[type="checkbox"] + label::after {
  position: absolute;
  display: inline-block;
  content: '';
  height: 14px;
  width: 14px;
  border: 1px solid white;
  border-radius: 50%;
  background-color: white;
  top: 4px;
  right: -33px;
}
.switch input[type="checkbox"]:checked + label::after {
  right: -48px;
}
.switch input[type="checkbox"] {
  display: none;
}
<div class="switch">
  <input type="checkbox" id="checkbox1">
  <label for="checkbox1">Lorem ipsum Test</label>
</div>
<div class="switch">
  <input type="checkbox" id="checkbox2">
  <label for="checkbox2">Test1</label>
</div>
<div class="switch">
  <input type="checkbox" id="checkbox3">
  <label for="checkbox3">Lorem ipsum Test2</label>
</div>

Upvotes: 3

Related Questions