I have the following structure, when the label is required, there’s a star next to the label. The problem that I’m having is that if the label has an icon and tooltip inside, it get’s between the label and the star. What could be the possible solution to always have the start right after the label?
.required:after {
content: '*';
}
<label for="input-required" class="required">
Label
<span class="tooltip">
<i class="icon icon-info"></i>
<span class="message top">Message</span>
</span>
</label>
In the case where there is an icon in a span element, put the * on a before pseudo element on the direct-child span. It will then come before the contents of that span.
In the case where the label does not have span content, put the * on the after pseudo element on the label.
This can be achieved using CSS :has pseudo class.
.required::after,
.required>span::before {
content: '*';
}
.required:has(span)::after {
content: '';
}
<label for="input-required" class="required">
Label with span
<span class="tooltip">
<i class="icon icon-info"></i>
<span class="message top">Message</span>
</span>
</label>
<br>
<label for="input-required" class="required">
Label no span
</label>
If you have to support browsers which do not have the :has implemented then this hack gives the same effect, except there is a character width after the element.
What is does is overlay the * at the end of the label with a little white (or whatever the background color is) rectangle so it is not seen.
.required {
margin-top: 100px;
position: absolute;
}
.required>span {
position: relative;
background: white;
}
.required::after,
.required>span::before {
content: '*';
}
.required>span::after {
content: '*';
color: transparent;
position: absolute;
width: fit-content;
height: fit-content;
background-color: inherit;
}
<label for="input-required" class="required">
Label with span
<span class="tooltip">
<i class="icon icon-info"></i>
<span class="message top">Message</span>
</span>
</label>
<br>
<label for="input-required" class="required">
Label no span
</label>