11

I have code like this:

span {
  border-radius: 50%;
  background-color: #d8d9dd;
  border: 6px solid #262c40;
  width: 25px;
  height: 25px;
  margin: 30px 0 0 40px;
  display: block;
}
span:before {
  content: attr(data-value);
  position: relative;
  white-space: pre;
  display: inline;
  top: -27px;
  left: -29px;
  width: 200px;
  text-align: center;
}
<span data-value="November 2016"></span>
<span data-value="May 2016"></span>

How can I center the text inside :before pseudo element to be in the middle of the span? Is it possible?

jcubic
  • 56,835
  • 46
  • 206
  • 357
  • refer https://stackoverflow.com/a/63173675/12872199 for the most LOGICAL and correct answer (not hit and trail positioning)! ;) – ashuvssut Jul 30 '20 at 12:59

6 Answers6

16

The best thing would be to position the before pseudo element absolutely with respect to the span using the popular centering technique:

top: 0;
left: 50%;
transform: translate(-50%, -25px);

Note that -25px is to offset the text above the circles (which has height 25px) - see demo below:

span {
  border-radius: 50%;
  background-color: #d8d9dd;
  border: 6px solid #262c40;
  width: 25px;
  height: 25px;
  margin: 30px 0 0 40px;
  display: block;
  position:relative;
}
span:before {
  content: attr(data-value);
  position: absolute;
  white-space: pre;
  display: inline;
  top: 0;
  left: 50%;
  transform: translate(-50%, -25px);
}
<span data-value="November 2016"></span>
<span data-value="May 2016"></span>
kukkuz
  • 39,721
  • 6
  • 52
  • 88
4

From MDN:

[the :before pseudo-element] is inline by default

Giving inline elements a width does nothing, so you need to style it as display: block (or inline-block if that is more appropriate). It also turns out that you need to adjust the left value to approximately -88px to get the text centred over the circle.

span {
  border-radius: 50%;
  background-color: #d8d9dd;
  border: 6px solid #262c40;
  width: 25px;
  height: 25px;
  margin: 30px 0 0 40px;
  display: block;
}
span:before {
  content: attr(data-value);
  position: relative;
  white-space: pre;
  display: inline;
  top: -27px;
  left: -88px;
  width: 200px;
  text-align: center;
  display: block;
}
<span data-value="November 2016"></span>
<span data-value="May 2016"></span>
lonesomeday
  • 224,675
  • 49
  • 309
  • 312
  • Though not explicitly mentioned, it should be noted that the `width` on the pseudo element is essential, as it alone gives it the space in which to be centred, otherwise it is just centred in its own length, effectively giving it the same alignment as the `li` item. – Patanjali Jan 12 '19 at 01:51
2

I recommend against using negative translations. It might end up outside the viewport if you don't do it enough carefully.

Moreover, you shouldn't insert contents with pseudo-elements. Pseudo-elements should only be used for styling purposes. Like this:

body {
  display: inline-block;
}
span {
  display: block;
  text-align: center;
}
span:after {
  content: '';
  border-radius: 50%;
  background-color: #d8d9dd;
  border: 6px solid #262c40;
  width: 25px;
  height: 25px;
  margin: 10px auto 30px;
  display: block;
}
<span>November 2016</span>
<span>May 2016</span>

The text inside the span is centered due to text-align: center.

The pseudo-element circle is centered due to margin-left: auto and margin-right: auto.

Oriol
  • 249,902
  • 55
  • 405
  • 483
  • I'm trying to modify the jQuery UI slider by adding labels for handlers I don't think that it will work when you have text inside spans. – jcubic Nov 24 '16 at 17:04
0

I was beaten to this, but here is my solution:

span {
   border-radius: 50%;
   background-color: #d8d9dd;
   border: 6px solid #262c40;
   width: 25px;
   height: 25px;
   margin: 30px 0 0 40px;
   display: block;
}
span:before {
   content: attr(data-value);
   position: relative;
   white-space: pre;
   display: inline-block;
   top: -27px;
   left: -50px;
   width: 125px;
   text-align: center;
}

The changes are to use inline-block display on the :before style and to adjust the left and width of the text.

Chris Peacock
  • 3,627
  • 2
  • 25
  • 23
0

Add display:inline-block; and add margin-left:-87px. where 87px derived from

100px(50% of whole width 200px)-13px(50% of span width 25px)

span {
  border-radius: 50%;
  background-color: #d8d9dd;
  border: 6px solid #262c40;
  width: 25px;
  height: 25px;
  margin: 30px 0 0 40px;
  display: block;
}
span:before {
  content: attr(data-value);
  position: relative;
  white-space: pre;
  display: inline-block;
  top: -27px;/*
  left: -29px;*/  
  margin-left: -87px;
  width: 200px;
  text-align: center;
}
<span data-value="November 2016"></span>
<span data-value="May 2016"></span>
jafarbtech
  • 6,339
  • 1
  • 33
  • 52
0

We should use LOGICAL CODE and not any hit and trail and playing around with numbers!

I used flex in the pseudo element to center it first upon the span element.

Then i used transform to Logically position the pseudo element.

/*styling to just make the presentation look good*/
body{
  border:5px solid black;
  padding:50px;
  display:flex;
  flex-direction: column;
  justify-content:center;
  align-items:center;
}

/* main stylings start here*/
span {
  border-radius: 50%;
  background-color: #d8d9dd;
  border: 6px solid #262c40;
  width: 25px;
  height: 25px;
  margin: 30px 0 0 40px;
  display: block;
}
span:before {
  content: attr(data-value);
  width:150px;
  border:solid black 1px;
  
  /*use flex to center it to middle & upon the span*/
  display:flex;
  justify-content:center;
  align-items:center;
  
  /*use transform and position it LOGICALLY (by considering border widths of the parent span and ofcourse using calc() )*/
  transform: translate(calc(-50% + 2 * 6px), calc(-100% - 6px));
}
<span data-value="November 2016"></span>
<span data-value="May 2016"></span>

I would request to use LOGICAL Code rather than design-breaking hit and trail values. Write Responsive Code. Happy Coding!

ashuvssut
  • 909
  • 5
  • 15