13

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
  • 61,973
  • 54
  • 229
  • 402
  • 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

8 Answers8

17

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>

Source

warren wiser
  • 57
  • 2
  • 10
kukkuz
  • 41,512
  • 6
  • 59
  • 95
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
  • 233,373
  • 50
  • 316
  • 318
  • 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
  • 274,082
  • 63
  • 437
  • 513
  • 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
2

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
  • 1,725
  • 9
  • 17
  • Note that the question is from 2016 I don't think that there was a flex box back then. But is a very good answer. I'm adding a comment right now because someone upvoted my question and I've revisited the answers in 2022. – jcubic Jul 20 '22 at 19:16
  • display flex rescued me for a similar issue of adding a fontawesome map pin to an address. Nice one. – debonator Aug 17 '22 at 10:43
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
  • 4,107
  • 3
  • 26
  • 24
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,842
  • 1
  • 36
  • 55
0

In my case I needed to center horizontally an html symbol inside pseudo's content element,so I used line-height property :

details summary::after{
    content: "›";
    border-radius: 100%;
    position: absolute;
    color: #64C1E3 ;
    right: 10px;
    top: 20px;
    width: 20px;
    height: 20px;
    display: flex;
    z-index: 1;
    border: 1px solid #64C1E3;
    transform: rotate(90deg);
    justify-content: center;
    font-size: 30px;
    line-height: 14px;
    font-family: emoji;
    transition: .5s;
}
jcubic
  • 61,973
  • 54
  • 229
  • 402
O'talb
  • 81
  • 1
  • 2
-2

Doing this always works for me:

put some content in the element first and the change in the z-index property of it in the CSS

Example:

Your HTML file

<p>some content</p>

Your CSS file

p{
  z-index:10;
}

p::after{
  content:'';
  /*rest of the code*/
}

/*use z-index as per your requirements*/
sadeq shahmoradi
  • 1,395
  • 1
  • 6
  • 22
Ullas
  • 1