2

Originally I needed this for a chat app. Now I need it for something else as well... I figure I'd better ask.

Elaborating the chat app example: chat messages are lis, they have two spans: one for the author's nick, the other one for the message, I'd like the size of all spans to be equal (for aesthetic purposes) and grow to fit the longest nick.

Failed attempts:

1. Flexbox

span {
  margin-top: 10px;
}

.author {
  font-weight: bold;
  margin-right: 5px;
}

.author:after {
  content: ":";
}

.message {
  flex: auto;
}

li {
  display: flex;
}
<ul>
  <li><span class="author">nick</span><span class="message">Don't you Remember, the Fifth of November, 'twas Gunpowder Treason Day, I let off my gun, and made'em all run. And Stole all their Bonfire away.</span></li>
  <li><span class="author">SomeOtherLongerNick</span><span class="message">Miss Susie had a steamboat, the steamboat had a bell. The steamboat went to Heaven, Miss Susie went to ...</span></li>
</ul>

As you can see the width of the nick field is not equal among messages which, IMO, is ugly.

2. Fixed width

span {
  position: relative;
  display: inline-block;
  margin-top: 10px;
}

.author {
  font-weight: bold;
  margin-right: 5px;
  width: 30%;
  text-align: right;
  vertical-align: top;
}

.author:after {
  content: ":";
}

.message {
  width: 65%;
}

ul {
  list-style-type: none;
  padding-left: 0;
}
<ul>
  <li><span class="author">nick</span><span class="message">Don't you Remember, the Fifth of November, 'twas Gunpowder Treason Day, I let off my gun, and made'em all run. And Stole all their Bonfire away.</span></li>
  <li><span class="author">nick2</span><span class="message">Miss Susie had a steamboat, the steamboat had a bell. The steamboat went to Heaven, Miss Susie went to ...</span></li>
</ul>

As you can see the width doesn't adapt to the lengths of the nicks with the result being a large waste of space.

3. Grid

div {
  display: grid;
  grid-template-columns: repeat(2, auto);
}

.author {
  font-weight: bold;
  margin-right: 5px;
  text-align: right;
}

.author:after {
  content: ":";
}

span {
  margin-top: 10px;
}
<div>
  <span class="author">nick</span><span class="message">Don't you Remember, the Fifth of November, 'twas Gunpowder Treason Day, I let off my gun, and made'em all run. And Stole all their Bonfire away.</span>
  <span class="author">OtherNick</span><span class="message">Miss Susie had a steamboat, the steamboat had a bell. The steamboat went to Heaven, Miss Susie went to ...</span>
</div>

This seems to work (gives the desired result) but nonetheless I list this among failed attempts for two reasons:

  1. This requires me to get rid of lis and bring all spans to the outer level. This, IIUC, breaks the semanticity of HTML markup, since semantically all those spans are not on the same level and hence should be grouped.
  2. This makes things more cumbersome if I want to, for example, provide borders, shading, etc, to chat entries. Instead of applying styles to a single li, I have to apply them to two spans and be careful to make them overlap correctly.

What is the correct way to achieve what I want to achieve?

1 Answers1

1

You are almost good with your grid solution. You can keep the li element by introducing display:contents (https://caniuse.com/#feat=css-display-contents) but you will still not be able to style the li since this one will no more generate a box content:

ul {
  display: grid;
  grid-template-columns: repeat(2, auto);
}
li {
  display:contents;
}

.author {
  font-weight: bold;
  margin-right: 5px;
  text-align: right;
}

.author:after {
  content: ":";
}

span {
  margin-top: 10px;
}
<ul>
  <li><span class="author">nick</span><span class="message">Don't you Remember, the Fifth of November, 'twas Gunpowder Treason Day, I let off my gun, and made'em all run. And Stole all their Bonfire away.</span>
  </li>
  <li><span class="author">OtherNick</span><span class="message">Miss Susie had a steamboat, the steamboat had a bell. The steamboat went to Heaven, Miss Susie went to ...</span></li>
</ul>

Another way is to consider display:table like below:

ul {
  display: table;
}

li {
  display: table-row;
}

.author {
  font-weight: bold;
  padding-right: 5px;
  text-align: right;
}

.author:after {
  content: ":";
}

span {
  padding-top: 10px;
  display: table-cell;
}
<ul>
  <li><span class="author">nick</span><span class="message">Don't you Remember, the Fifth of November, 'twas Gunpowder Treason Day, I let off my gun, and made'em all run. And Stole all their Bonfire away.</span>
  </li>
  <li><span class="author">OtherNick</span><span class="message">Miss Susie had a steamboat, the steamboat had a bell. The steamboat went to Heaven, Miss Susie went to ...</span></li>
</ul>
Temani Afif
  • 180,975
  • 14
  • 166
  • 216
  • Awesome, thank you! Though, it's worthy to mention, your second table example requires border-spacing for the rows to be separated, as margin is ignored : https://stackoverflow.com/questions/16398823/why-is-a-div-with-display-table-cell-not-affected-by-margin –  Nov 22 '18 at 20:52
  • @gaazkam that's why I used padding in the second example ;) – Temani Afif Nov 22 '18 at 20:53
  • Yeah but I mean this last `span { margin-top: 10px; }` –  Nov 22 '18 at 20:56