Brammz
Brammz

Reputation: 389

How to add margin only on line break?

I am trying to add a margin-bottom when a string is split into multiple lines.

I read about box-decoration-break, but that does not seem to do what I'm trying to achieve.

The following code snippet below shows what I'm trying to do (only the last row should have a margin-bottom).

div {
  max-width: 250px;
}

table {
  border-collapse: collapse;
}

table, th, td {
  border: 1px solid black;
}

td div {
  margin-bottom: 25px;
}
<div>
  <table>
    <tr>
       <td>One</td>
       <td>1</td>
       <td>
          <div>This is a short string</div>
       </td>
    </tr>
    <tr>
       <td>Two</td>
       <td>2</td>
       <td>
          <div>This is a short string</div>
       </td>
    </tr>
    <tr>
       <td>Three</td>
       <td>3</td>
       <td>
          <div>This string is way too long so it will be broken</div>
       </td>
    </tr>
  </table>
<div>

Upvotes: 3

Views: 3193

Answers (1)

Buszmen
Buszmen

Reputation: 2426

Every place I search for the answer says it's impossible, so we need a serious witchcraft and a little bit of limitations you have to agree to.

table {
  border-collapse: collapse;
}

table, th, td {
  border: 1px solid black;
}
td span {
  display: inline-block;
}

div {
  width: 250px;
}
td span:after {
  content: "";
  margin-top: calc((100% - 250px + 1px / 10) * 16 * 10);
  display: block;
}
<div>
  <table>
    <tr>
       <td>One</td>
       <td>1</td>
       <td>
         <div><span>This is a short string</span></div>
       </td>
    </tr>
    <tr>
       <td>Two</td>
       <td>2</td>
       <td>
         <div><span>This is a short string</span></div>
       </td>
    </tr>
    <tr>
       <td>Three</td>
       <td>3</td>
       <td>
         <div><span>This string is way too long so it will be broken</span></div>
       </td>
    </tr>
  </table>
<div>

The best idea I've come to is to add margin based on the height, cause two and more lines makes it higher. Unfortunately percentages for heights, margins, padding, borders and probably everything else is based on parent's ... width.

So let's work with what we've got. Wrapped text means that the width reaches its maximum - let's say 250px. One line means the width must be less than 250px. So let's subtract max 250px from whatever width we have. We will end up with either negative number or 0 if it reaches max width. Now let's add 1px and multiply it by current font-size (16px). Now keep in mind that for extreme edge case where the text ends up having 249.5px we will have half of the margin below :(. To mitigate this we can reduce 1px n times and multiply it n times back with our font-size. The smaller the value, the safer it gets.

Limitations:

  • The width of the container must be known (fixed) because you have to subtract if from 100%.
  • Font size or height of the margin must be in "pixels" as well. To multiply our tiny bit unit based values cannot be used (1em won't work).
  • We need to wrap text with additional tag so the parent's width is based on the text (inline or similar). You can get rid of the div if you make sure this column's width stays the same.

Hope it helps ;)

Upvotes: 2

Related Questions