Categories
Development

Merging elements in a CSS selector

I already have a CSS/HTML mockup that makes it look like WhatsApp messaging, but only for conversations between 2 people. I want to add the group-chat feature, which means the names.

It’s based on a <dl> list, so the HTML looks like this:

.whatsapp {
  width: 100%;
  max-width: 320px;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  display: table;
  margin: auto;
  background-image: url("https://raw.githubusercontent.com/Azdaema/AO3-Skin_Messaging/master/WhatsApp/images/WhatsApp_background.png");
  background-repeat: repeat-y;
  background-size: 100%;
}

.whatsapp dt {
  display: none;
}

.whatsapp dd {
  max-width: 65%;
  clear: both;
  position: relative;
  color: #000000;
  border-radius: 5px;
  padding: 5px;
  margin: 1px 15px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.2);
  z-index: 1;
}

.whatsapp dd:after {
  content: attr(time);
  font-size: 0.75em;
  color: #999;
  text-transform: uppercase;
  display: inline-block;
  float: right;
  line-height: 1.3em;
  padding-top: 0.5em;
  padding-left: 1.5em;
  margin: 0;
}

.whatsapp dd:last-child {
  margin-bottom: 10px;
}

.whatsapp dd:last-child:before {
  content: "";
  position: absolute;
  width: 25px;
  height: 14px;
  bottom: 5px;
  border-top: 9px solid;
  border-radius: 20px;
  z-index: -1;
}


/*
 * Outgoing texts
 */

.whatsapp .out dd {
  float: right;
  background: #DCF8C6;
}

.whatsapp .out dd:last-child:before {
  border-color: #DCF8C6;
  transform: rotate(240deg);
  right: -16px;
}


/*
 * Incoming texts
 */

.whatsapp .in dd {
  float: left;
  background: #FFFFFF;
}

.whatsapp .in dd:last-child:before {
  border-color: #FFFFFF;
  transform: rotate(-240deg);
  left: -16px;
}


/*
 * Timestamps
 */

.whatsapp .day,
.whatsapp dd sub {
  font-family: inherit;
  font-size: 0.75em;
  color: #999;
  text-transform: uppercase;
}

.whatsapp .day {
  width: 100px;
  background: #D4EAF4;
  border-radius: 5px;
  padding: 5px;
  margin: 10px auto;
  text-align: center;
  display: table;
}

.whatsapp dd sub {
  display: inline-block;
  float: right;
  line-height: 1.3em;
  padding-top: 0.5em;
  padding-left: 1.5em;
  margin: 0;
}


/* checkmarks */

.whatsapp .out dd sub:after {
  content: url("https://raw.githubusercontent.com/Azdaema/AO3-Skin_Messaging/master/WhatsApp/images/Checkmark_read.png");
  margin-left: 3px;
}

.whatsapp .out dd sub.received:after {
  content: url("https://raw.githubusercontent.com/Azdaema/AO3-Skin_Messaging/master/WhatsApp/images/Checkmark_received.png");
}

.whatsapp .out dd sub.notreceived:after {
  content: url("https://raw.githubusercontent.com/Azdaema/AO3-Skin_Messaging/master/WhatsApp/images/Checkmark_no-received.png");
}


/*
 * Big emojis
 */

.whatsapp dd.emoji1 {
  font-size: 2.5em;
}

.whatsapp dd.emoji2 {
  font-size: 2em;
}

.whatsapp dd.emoji3 {
  font-size: 1.5em;
}

.whatsapp dd.emoji1 sub,
.whatsapp dd.emoji2 sub,
.whatsapp dd.emoji3 sub {
  display: block;
  float: none;
  text-align: right;
  padding: 0 !important;
}

.whatsapp dd.emoji1 sub {
  font-size: 0.3em;
}

.whatsapp dd.emoji2 sub {
  font-size: 0.375em;
}

.whatsapp dd.emoji3 sub {
  font-size: 0.5em;
}


/*
 * Pictures
 */

.whatsapp .pic {
  padding: 3px;
}

.whatsapp .pic img {
  border-radius: 3px;
  width: 100%;
  display: block;
}


/* Timestamp white and in image corner */

.whatsapp .pic.solo sub {
  color: #ffffff;
  position: absolute;
  bottom: 2px;
  right: 5px;
}


/*
 * Contact header
 */

.whatsapp .contact {
  position: relative;
  background: #075E54;
  margin: 0;
  padding: 10px;
  font-family: inherit;
  color: #FFFFFF;
  font-size: 15px;
  font-weight: bold;
  text-transform: capitalize;
  text-align: left;
}


/* avatar circle */

.whatsapp .contact:before {
  content: "";
  float: left;
  width: 35px;
  height: 35px;
  background-image: url("https://t3.ftcdn.net/jpg/00/64/67/80/240_F_64678017_zUpiZFjj04cnLri7oADnyMH0XBYyQghG.jpg");
  background-size: 100%;
  border-radius: 100%;
  margin-right: 10px;
}


/* Online status */

.whatsapp .contact.online:after {
  content: "Online";
  display: block;
  padding-top: 5px;
  font-size: 13px;
  font-weight: normal;
}


/*
 * Group chat
 */

.whatsapp.grouptext .in dt {
  display: table !important;
  clear: both;
  font-weight: bold;
  padding-left: 15px;
}

.whatsapp.grouptext .in.p1 dt {
  color: #e54c51;
}

.whatsapp.grouptext .in.p2 dt {
  color: #ee7d37;
}

.whatsapp.grouptext .in.p3 dt {
  color: #dfa64f;
}

.whatsapp.grouptext .in.p4 dt {
  color: #58b042;
}

.whatsapp.grouptext .in.p5 dt {
  color: #58bfe8;
}

.whatsapp.grouptext .in.p6 dt {
  color: #367cdc;
}

.whatsapp.grouptext .in.p7 dt {
  color: #6f4bf5;
}

.whatsapp.grouptext .in.p8 dt {
  color: #ec68a1;
}
<dl class="whatsapp grouptext">
  <div class="out">
    <dt>Ciri</dt>
    <dd time="2:01 PM">Who's picking me up today?</dd>
  </div>

  <div class="in p1">
    <dt>Yennefer</dt>
    <dd>its tuesday</dd>
    <dd>so jaskier</dd>
  </div>

  <div class="in p2">
    <dt>Jasker</dt>
    <dd>no its geralts turn</dd>
    <dd>i swear its his turn</dd>
  </div>

  <div class="in p3">
    <dt>Geralt</dt>
    <dd>no, Yen is right: it's your turn</dd>
    <dd>it's tuesday</dd>
    <dd>Tuesday is always your turn</dd>
  </div>
</dl>

<hr>

<dl class="whatsapp">
  <h1 class="contact online">Mabel</h1>
  <h4 class="day">Today</h4>

  <div class="out">
    <dt>Dipper</dt>
    <dd>How's babysitting for Soos and Melody going?<sub>11:49 AM</sub>
    </dd>
  </div>

  <div class="in">
    <dt>Mabel</dt>
    <dd>So I made chicken nuggets for lunch<sub>1:07 PM</sub>
    </dd>
    <dd>And you remember how much we used to love chicken nuggets!!!!! but when I tried one now it was just kind of bland and gross<sub>1:07 PM</sub>
    </dd>
    <dd>How sad is that??!<sub>1:07 PM</sub>
    </dd>
    <dd>I feel like an adult and I hate it<sub>1:07 PM</sub>
    </dd>
  </div>

  <div class="out">
    <dt>Dipper</dt>
    <dd>Does it help if I say texting me to lament about chicken nuggets is super un-adult?<sub>1:08 PM</sub>
    </dd>
  </div>

  <div class="in">
    <dt>Mabel</dt>
    <dd>maybe a little<sub>1:08 PM</sub>
    </dd>
  </div>

  <div class="out">
    <dt>Dipper</dt>
    <dd>I bet we could make good chicken nuggets at home if we tried<sub>1:08 PM</sub>
    </dd>
  </div>

  <div class="in">
    <dt>Mabel</dt>
    <dd class="emoji1">👀<sub>1:08 PM</sub>
    </dd>
  </div>

  <div class="out">
    <dt>Dipper</dt>
    <dd>I mean it's just bite-sized breaded chicken, right? You still like chicken and bread<sub>1:09 PM</sub>
    </dd>
  </div>

  <div class="in">
    <dt>Mabel</dt>
    <dd>loving this can-do spirit brobro<sub>1:09 PM</sub>
    </dd>
    <dd>Also it makes you sound like antoni on queer eye<sub>1:09 PM</sub>
    </dd>
  </div>

  <div class="out">
    <dt>Dipper</dt>
    <dd>Making An Effort 👍<sub>1:10 PM</sub>
    </dd>
    <dd>and making chicken nuggets<sub>1:10 PM</sub>
    </dd>
  </div>

  <div class="in">
    <dt>Mabel</dt>
    <dd>:swoon:<sub>1:10 PM</sub>
    </dd>
    <dd>Oooooh can we make them dinasour shaped<sub>1:11 PM</sub>
    </dd>
  </div>

  <div class="out">
    <dt>Dipper</dt>
    <dd>I think the reason they can make the store bought ones shaped is because they're not actually made out of chicken, they're made out of paste<sub>1:11 PM</sub>
    </dd>
    <dd>wait<sub>1:11 PM</sub>
    </dd>
    <dd>Shit did I just destroy our childhood?<sub>1:11 PM</sub>
    </dd>
  </div>

  <div class="in">
    <dt>Mabel</dt>
    <dd>No<sub>1:11 PM</sub>
    </dd>
    <dd>Maybe a little<sub>1:12 PM</sub>
    </dd>
  </div>

  <div class="out">
    <dt>Dipper</dt>
    <dd>We could take real chicken and grind it up??<sub>1:13 PM</sub>
    </dd>
    <dd>It works for hamburgers. Mix in onion and stuff<sub>1:13 PM</sub>
    </dd>
  </div>

  <div class="in">
    <dt>Mabel</dt>
    <dd>I can't decide if onion would be good, or if it would be sacrilegious to the spirit of chicken nuggets<sub>1:13 PM</sub>
    </dd>
  </div>

  <div class="out">
    <dt>Dipper</dt>
    <dd>If they have onion but are dinosaur shaped, would that be a fair trade?<sub>1:14 PM</sub>
    </dd>
  </div>

  <div class="in">
    <dt>Mabel</dt>
    <dd>yes<sub>1:14 PM</sub>
    </dd>
    <dd class="emoji2">🦕🦖<sub>1:14 PM</sub>
    </dd>
    <dd>ALL THE SHAPES!!<sub>1:14 PM</sub>
    </dd>
    <dd class="emoji3">🦚🦑🪐<sub>1:14 PM</sub>
    </dd>
  </div>

  <div class="out">
    <dt>Dipper</dt>
    <dd>That seems ambitious<sub>1:14 PM</sub>
    </dd>
  </div>

  <div class="in">
    <dt>Mabel</dt>
    <dd>Bread on the outside! Bread on the inside!<sub>1:15 PM</sub>
    </dd>
  </div>

  <div class="out">
    <dt>Dipper</dt>
    <dd>If the bread was on the inside the chicken would dry out<sub>1:15 PM</sub>
    </dd>
  </div>

  <div class="in">
    <dt>Mabel</dt>
    <dd>beef jerky is good<sub>1:15 PM</sub>
    </dd>
  </div>

  <div class="out">
    <dt>Dipper</dt>
    <dd>Fair poin<sub>1:16 PM</sub>t</dd>
  </div>

  <div class="in">
    <dt>Mabel</dt>
    <dd>CHICKEN NUGGET CINNAMON ROLLS!!!<sub>1:16 PM</sub>
    </dd>
    <dd>bread on the inside AND the outside<sub>1:16 PM</sub>
    </dd>
  </div>

  <div class="out">
    <dt>Dipper</dt>
    <dd>To what ends?<sub>1:16 PM</sub>
    </dd>
  </div>

  <div class="in">
    <dt>Mabel</dt>
    <dd>Defying chicken-bread roles<sub>1:17 PM</sub>
    </dd>
    <dd>why does the bread always have to be on the outside, shielding the chicken from the drying heat of the oven?? Doesn't bread deserve to be protected sometimes too<sub>1:17 PM</sub>
    </dd>
  </div>

  <div class="out">
    <dt>Dipper</dt>
    <dd>Can't argue with that<sub>1:17 PM</sub>
    </dd>
    <dd>Wait so were you actually serious about making chicken nuggets?? I'm at the store now, should I buy some chicken?<sub>3:47 PM</sub>
    </dd>
  </div>

  <div class="in">
    <dt>Mabel</dt>
    <dd>yes get chicken<sub>4:11 PM</sub>
    </dd>
  </div>

  <div class="out">
    <dt>Dipper</dt>
    <dd>Mabel we've talked about this<sub>4:12 PM</sub>
    </dd>
    <dd>When I say "I'm at the store NOW" you can't reply half an hour later still asking for stuff<sub>4:12 PM</sub>
    </dd>
    <dd>but yeah I got chicken<sub>4:16 PM</sub>
    </dd>
  </div>

  <div class="in">
    <dt>Mabel</dt>
    <dd class="emoji1">💖<sub>4:16 PM</sub>
    </dd>
  </div>

</dl>

View on CodePen

In WhatsApp group chat, the name appears as the top line of the first text that person sends in a series.

What I want:

enter image description here

At first I just tried this, to make some space, and then translated the name into place.

.whatsapp.grouptext .incoming dt+dd {
  padding-top: 1.5em;
}

But if someone just says “no” or something, then the text bubble is that narrow, and it’s not wide enough for the name. Both names and texts can vary in length, and I’d really rather not hard-code either to a fixed pixel size or something.

What I really want is to merge the two into a single element, or to turn the contents of <dt> into a :before for <dd>. Is there any way to do that?

(And yes, I could just wrap those top two in a <div> or whatever. But is there any other way??)

Leave a Reply

Your email address will not be published. Required fields are marked *