moogal
moogal

Reputation: 1639

Vertically aligning text along the same line across different containers

I have a container with two other pieces of text inside it - a title and a description, for example:

.item {
  box-sizing: border-box;
  width: 33%;
  text-align: center;
  padding: 20px;
  border: 1px solid #CCC;
  min-height: 200px;
  margin: 20px;
}

.item-title {
  font-size: 28px;
  margin-bottom: 15px;
}

.item-description {
  font-size: 12px;
}
<div class="item">
  <div class="item-title">Title</div>
  <div class="item-description">Some descriptive text</div>
</div>

<div class="item">
  <div class="item-title">A Much Longer Title</div>
  <div class="item-description">Some other descriptive text</div>
</div>

Here's a diagram of the desired effect:

diagram of desired effect

What I'd like is for the title to be vertically-centred at the same point (blue line), no matter how many lines it wraps over. The description should always stay underneath, the same distance away from the title, top-aligned (red line). So the blue line doesn't move but the red line can.

What I've tried so far:

After experimenting for a while and a lot of reading up, it seems like it might not be possible, but if anyone's managed to solve this I'd be very interested to know how.

Upvotes: 3

Views: 1031

Answers (1)

Michael Benjamin
Michael Benjamin

Reputation: 371231

I agree with you. I don't think this is possible with CSS alone.

Your requirements:

What I'd like is for the title to be vertically-centred at the same point (blue line), no matter how many lines it wraps over. The description should always stay underneath, the same distance away from the title, top-aligned (red line). So the blue line doesn't move but the red line can.

The following solution satisfies requirement #1 (blue line). The titles are centered along the same horizontal line.

  • Make the top-level parent (.item) a flex container.

  • Give the first child (.item-title) a set proportion of the container space. In my example below, I used flex-grow: 3.

  • Also give the second child (.item-description) a set proportion of the container space. I used flex-grow: 1.

  • Now vertical centering can be uniform across both containers because they are occupying the same proportions of free space.

  • However, the descriptions will also be a proportional distance away from the title element, and cannot remain anchored to the same horizontal axis (red line).

.item {
  display: inline-flex;
  flex-direction: column;
  vertical-align: top;
  width: 33%;
  text-align: center;
  padding: 20px;
  border: 1px solid #CCC;
  min-height: 200px;
  margin: 20px;
  box-sizing: border-box;
}

.item-title {
  flex: 3;
  font-size: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed red;
}

.item-description {
  flex: 1;           /* also try flex: 2 for a narrower gap between items */
  font-size: 12px;
  border: 1px dashed red;
}

hr {
  position: absolute;
  top: 100px;
  background: blue;
  width: 95vw;
}
<div class="item">
  <div class="item-title">Title</div>
  <div class="item-description">Some descriptive text</div>
</div>

<div class="item">
  <div class="item-title">A Much Longer Title</div>
  <div class="item-description">Some other descriptive text</div>
</div>
<hr>

jsFiddle demo 1


The following solution satisfies requirement #2 (red line). The descriptions are always the same distance away from the title. However, the titles are no longer anchored to the same horizontal axis.

  • Put both the title and description in a single flex container.
  • Use a top margin to set a fixed distance for the description from the title.
  • NOTE: The height of the description and vertical margins will determine how far off the line the title is. In other words, the smaller the description and top margin, the closer the titles get to the blue line goal.

.item-title {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex: 1;
  font-size: 28px;
  border: 1px dashed red;
}

.item-description {
  margin-top: 5px;
  font-size: 12px;
}

hr {
  position: absolute;
  top: 100px;
  width: 95vw;
}

/* non-essential decorative styles */
.item {
  display: inline-flex;
  vertical-align: top;
  width: 33%;
  text-align: center;
  padding: 20px;
  border: 1px solid #CCC;
  min-height: 200px;
  margin: 20px;
  box-sizing: border-box;
}
<div class="item">
  <div class="item-title">Title<span class="item-description">Some descriptive text</span>
  </div>
</div>

<div class="item">
  <div class="item-title">A Much Longer Title<span class="item-description">Some other descriptive text</span>
  </div>
</div>

<hr>

jsFiddle demo 2

Upvotes: 2

Related Questions