1

I have blurry text when using transform: translate(-50%,-50%); to center an absolutely positioned div on my screen.

I have tried tons of different solutions (mostly from here and here) and nothing works except making the width and height of the div an even number.

That is, if the height is 77px instead of 76px then the inner text is blurry. Likewise if the div width is 163 px instead of 162 px then it's blurry.

Is there a way to ensure the width and height of a dynamic div is an even number?

Using JavaScript seems like a no-go because not only is it complex but it would cause the element to flash to a different width immediately after being rendered (need to render it to first find out the width) which is unpleasant for the user to see.

Also, I can't just hardcode the width and height because the contents are dynamic. Also, if I could hardcode the width to, say, 100px, then I wouldn't even need this issue, because I could just do something like transform: translate(calc(-50% - 50px),-50%); to sidestep the issue.

Here's a code example:

.outer {
  margin: 0 auto;
  width: 500px;
  border: 1px solid #ddd;
  height: 50px;
  position: relative;
}

.inner {
  position: absolute;
  left: 50%;
  top: 25px;
  transform: translate(-50%, -50%);
  background-color: #dfdfdf;
  padding: 5px;
  font-family: Inter;
}
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">

<div class="outer">
  <div class="inner">
    <b> asdf </b> blurrya
  </div>
</div>
Ryan Peschel
  • 11,087
  • 19
  • 74
  • 136
  • Have you considered a different approach to centering your div? Tried flexbox? – Wesley Sep 12 '20 at 21:46
  • It's absolutely positioned on the screen so I cannot use flexbox. That is, it's not a part of the document flow and should be rendered on top of them. – Ryan Peschel Sep 12 '20 at 21:47
  • I'm not sure how that helps but sure I'll add one. One second – Ryan Peschel Sep 12 '20 at 21:48
  • In terms of the flashing when setting dimensions using JavaScript - could you start the element as visibility: hidden and show it once you have sized it? – patrickb Sep 12 '20 at 21:53
  • @patrickb I suppose that's possible, but that seems like quite the mess to have to do just to get this to work (start off invisible, measure, calculate width and height, potentially increment by 1, and then show) – Ryan Peschel Sep 12 '20 at 21:54
  • But do you have to use absolute position for the child element, or are you just doing that so that you can vertically and horizontally center it? – Wesley Sep 12 '20 at 22:01
  • Yeah I don't see how I would do it without absolute positioning. The entire element is a short-lived notification that fades away and it is not a part of the regular document flow. – Ryan Peschel Sep 12 '20 at 22:04

1 Answers1

3

If you're willing to add one more element you can use flex within the absolutely positioned element to center the inner most element while maintaining its exclusion from the document flow.

.outer {
  margin: 0 auto;
  width: 500px;
  border: 1px solid #ddd;
  height: 50px;
  position: relative;
}

.inner {
  position: absolute;  
  
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.center {
    top: 25px;
    background-color: #dfdfdf;
    padding: 5px;
    font-family: Inter;
}
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">

<div class="outer">
  <div class="inner">
    <p class="center">
      <b>asdf </b> blurrya
    </p>
  </div>
</div>
pilchard
  • 12,414
  • 5
  • 11
  • 23