CSS Grid - unnecessary word break

2020-02-02 02:17发布

问题:

I have a problem with CSS grid.

In the following snippet extracted from the codebase, I have a very simple HTML structure with grid layout. Content is set to break-word to prevent text from overflowing. Event though there is enough space for the text to NOT get broken, it does create a line break just before the last letter.

My understanding was that in grid layout, by default, items are calculated to fit the content as much as possible, which is somehow not the case in this example.

Removing padding from content or margins from grid item does solve the issue, but margin is there for centering and padding is also needed.

Is there any property I have to or can use to solve this problem?

P.S. To my knowledge, the bug is not present in Firefox, I have found it in Chrome and Safari so far.

.grid {
  display: grid;
  grid-template-columns: auto;
}

.item {
  margin: 0 auto;
}

p {
  word-break: break-word;
  padding: 0 4%;
}
<div class="grid">
  <div class="item">
    <p>HOTEL</p>
    <p>GRAND</p>
  </div>
</div>

回答1:

It's not a bug but a complex calculation.

There is a kind of cycle to calculate the final width of the element which create the issue. The width is first calculated considering the content (a shrink-to-fit behavior based on the properties you used) then using percentage value with padding will consider the calculated width1. At the end, we will reduce the calculated padding from the width creating the word break.

This will happen with the smallest value since in all the cases the width will always be less than the needed width to contain the longest word:

.grid {
  display: grid;
  grid-template-columns: auto;
}
.item {
  margin:auto;
  border:1px solid;
}
.pad p {
  word-break: break-word;
  padding: 0 1%;
}
<div class="grid">
  <div class="item">
    <p>HOTEL</p>
    <p>I_WILL_FOR_SURE_BREAK</p>
  </div>
</div>

<div class="grid">
  <div class="item pad">
    <p>HOTEL</p>
    <p>I_WILL_FOR_SURE_BREAK</p>
  </div>
</div>

As you can see, the first grid with padding is shrinked to its content and the second grid is having exactly the same width and the padding is creating the line break.


An easy fix is to use pixel value instead of percentage in case you know the value you want:

.grid {
  display: grid;
  grid-template-columns: auto;
  justify-content:center;
}

.item {
  margin:auto;
  border:1px solid;
}

.pad p {
  word-break: break-word;
  padding: 0 20px;
}
<div class="grid">
  <div class="item">
    <p>HOTEL</p>
    <p>I_WILL_NOT_BREAK</p>
  </div>
</div>

<div class="grid">
  <div class="item pad">
    <p>HOTEL</p>
    <p>I_WILL_NOT_BREAK</p>
  </div>
</div>


Why you don't see this on firefox?

Simply because break-word is not supported there (https://developer.mozilla.org/en-US/docs/Web/CSS/word-break)

So you will have an overflow instead of a word break. You may notice this behavior on firefox if you use break-all:

.grid {
  display: grid;
  grid-template-columns: auto;
}
.item {
  margin:auto;
  border:1px solid;
}
p {
  word-break: break-all;
  padding: 0 1%;
}
<div class="grid">
  <div class="item">
    <p>HOTEL</p>
    <p>I_WILL_FOR_SURE_BREAK</p>
  </div>
</div>


1: The size of the padding as a percentage, relative to the width of the containing block.ref