Menu icon Foundation
Is there a simple method of centering text vertically?

I have a two column layout with an h3 a p in a left column and an image in the right. Wondering how to get the h3 and p to center vertically to the image—rather than just being flush top.

One method I am experimenting with now that "might" be promising is to write a rule for padding-top: 25%, and apply it only to the h3. This seems to position my h3 in a spot that I would consider "close enough for blues". Naturally, the paragraph get pushed down too. It sort of falls apart after the columns re-align on small view though, but perhaps I can resolve that using visibility classes and remove the class from the h3 on mobile or small screens.

If anyone else has a better, perhaps more correct way of accomplishing this feat, please do tell.

<div class="row">
  <div class="medium-4 columns text-center">
    <h3>Title Word</h3>
    <p>Tagline</p>
  </div>
  <div class="medium-8 columns">
    <img src="assets/images/sample1.jpg" />
  </div>
</div>        

         

textverticalmiddlealign

I have a two column layout with an h3 a p in a left column and an image in the right. Wondering how to get the h3 and p to center vertically to the image—rather than just being flush top.

One method I am experimenting with now that "might" be promising is to write a rule for padding-top: 25%, and apply it only to the h3. This seems to position my h3 in a spot that I would consider "close enough for blues". Naturally, the paragraph get pushed down too. It sort of falls apart after the columns re-align on small view though, but perhaps I can resolve that using visibility classes and remove the class from the h3 on mobile or small screens.

If anyone else has a better, perhaps more correct way of accomplishing this feat, please do tell.

<div class="row">
  <div class="medium-4 columns text-center">
    <h3>Title Word</h3>
    <p>Tagline</p>
  </div>
  <div class="medium-8 columns">
    <img src="assets/images/sample1.jpg" />
  </div>
</div>        

         
Jason Demitri over 2 years ago

If fixed height then you can you something like this

.parent {
  position: relative;
}

.child {
  width: 300px;
  height: 100px;
  padding: 20px;

  position: absolute;
  top: 50%;
  left: 50%;

  margin: -70px 0 0 -170px;
}

else this

.parent {
  position: relative;
}
.child {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

Full explanation here >> http://css-tricks.com/centering-css-complete-guide/

Marc McGee over 2 years ago

Not wanting to fix a height at this point, I'll give your else a try.

Thanks for the tips. Much better I think than my padding-top solution.

Marc McGee over 2 years ago

Gave the else a try and it puts the block of text in the upper right hand corner.

I wrapper the h2 & p with a div class of child. Also tried with and without .parent on the medium-5 column.

That cssTricks article is where I had started before I posted here. Certainly some great tips there. Re-reading now to see if I missed something.

Although – my little padding-top trick seems to work pretty good. Probably not exactly in the middle, but close enough. Then for mobile, I use visability classes to hide the code with my hack such that I don't have the extra padding-top on iPhone and iPad.

Marc McGee over 2 years ago

The Table approach seems to be a workable solution. Just need to write some custom styles to get rid of the foundation table border and cell padding, and I might be good to go.

<div class="row slh_featuredwrap hide-for-small">
  <div class="medium-12 columns">
<table>
  <tbody>
    <tr>
      <td width="40%">
          <h3>TITLE</h3>
          <p>Tagline goes here</p>
      </td>
      <td width="60%"><img src="assets/images/sample.jpg"  /></td>
    </tr>
  </tbody>
</table>
  </div>
</div>

<div class="row  show-for-small">
  <div class="medium-5 columns">
    <h3>TITLE</h3>
    <p>Tagline goes here</p>
    </div>
  <div class="medium-7 columns">
    <img src="assets/images/sample.jpg"  />
  </div>
</div>

Marc McGee over 2 years ago

Hi Rafi: Thanks for posting these. My table setup seems to be working fine, but I will take a look at what you've sent. Much appreciated.

Marc McGee over 2 years ago

I am revisiting my solution used for centering my block of text vertically, after reviewing the page layout using Sauce Labs. Windows 8.1 IE 10 test environments loads my image at full size. Rather than containing the image to the width of my Foundation table cell, the image is causing the table cell to increase in size to fit the image.

Not sure how to create a solution for the issue. Basically wanted a small block of text on the left that is centered vertically to the image to the right. Since this is responsive, I don't think I can set predetermined heights—which seems to be necessary for using any type of vertical centering of text — as in — you need to know what you're centering vertically to.

I'm going to review Rafi's links for potential solutions, but this kind of came out of left field. Works great on Mac using any of the browsers I have loaded, but the Windows IE scenario has thrown a monkey wrench into my plan.

Below was the simple solution that seemed to be working. Do I need to create a CSS rule for how the image is handled within the table cell?

Or, is there a better approach to achieve my goal?

<div class="row slh_featuredwrap">
  <div class="medium-12 columns">
<table>
  <tbody>
    <tr>
      <td width="45%">
          <h3>Title</h3>
          <p>3-Word Description</p>
      </td>

      <td width="55%">
          <img src="../myImage.jpg" />
      </td>

    </tr>
  </tbody>
</table>
  </div>
</div>
.slh_featuredwrap {
  padding-bottom: 1em;
  padding-top: 1em;
}
.slh_featuredwrap table {
  border: 0;
  margin-bottom: 0;
}
.slh_featuredwrap table tr td {
  font-size: 1rem;
  padding: 0;
  text-align: center;
}
.slh_featuredwrap p {
  color: #41c1ca;
  font-size: 0.85em;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}
.slh_featuredwrap h3, .slh_featuredwrap h4 {
  letter-spacing: 0.1em;
  margin-bottom: 0;
  text-transform: uppercase;
}

Marc McGee over 2 years ago

I'm reviewing the links that Rafi provided — in particular: Vertical align anything with just 3 lines of CSS.

My approach has been to create my two columns, and then place equalizer on the row and watch the two columns. So far so good. By applying a background color to my left column, I can see that equalizer is working.

I then wraps my text in the left column in a div with a class with the following declaration

.centerMeVertically {
  position: relative;
  top: 50%;
  transform: translateY(-50%);
}

It does appear to be "attempting" to center the block vertically, but not quite. There is more space above than below. Still trying to determine what is causing that.

Marc McGee over 2 years ago

Aha!

I sort of figured out what's happening. Visually, it looks like the top edge of my div is at 50%.

So... maybe I am applying the css rule incorrectly? Or maybe I need to apply it to elements individually, rather than a wrapping container?

Kind of lost at this point.

Robert Stark over 2 years ago

The method I use for F5:

.valign-middle .columns {
    display: table-cell;
    vertical-align: middle;
   }

.valign-middle .columns,
.valign-middle [class*="column"] + [class*="column"]:last-child {
    float: none;
}

@media only screen and (max-width: 40.063em) {
//small media displays  
  .valign-middle .small-12.columns {
    display: block;
    vertical-align: top;
}
}

HTML:

  <div class="row valign-middle collapse">
            <div class="small-12 medium-6 columns">Col1</div>
<div class="small-12 medium-6 columns">Col2</div>
</div>

Screen Shot:
http://awesomescreenshot.com/0d84mnkdf5

Marc McGee over 2 years ago

Thanks Robert:

I'll give this a try. Thank you for sharing.

Marc McGee over 2 years ago

Works great, except that the media query doesn't seem to be working. On small, all of the content vanishes. I see the content in the source code, but not onscreen.

Checked on Sauce labs, and again on IE 10, my image file in the right column is loading really really big, and throwing off the entire layout.

Marc McGee over 2 years ago

On the contrary: Using my centerMeVertically rule along with Equalizer does work. I use a visibility class to handle the content differently on mobile to remove centerMeVertically and Equalizer.

Here's what I notice though. As mention, on Mac in Safari, the cerntering seems to be based on the top edge of the div containing the text block I was to be centered vertically. However, in Sauce Labs, testing in Windows 8 IE 10, the text block appears to be perfectly centered. Great for IE 10 but not for Safari.

Just as I was thinking I could adjust the percentage in the rule to be something more like 35% — guestimating the approximate center, I see now that the change would inevitably mess up the display in IE10.

Marc McGee over 2 years ago

I've narrowed this down a bit and see that Safari seems to handle the following CSS rule differently.

.centerMeVertically {
  position: relative;
  top: 50%;
  transform: translateY(-50%);
}

I've placed the class on a div that wraps my h3 and p within a medium-3 columns.

My text block centers vertically just perfect on Mac using Chrome, and Sauce Labs shows it centering perfectly on Windows 8 IE 10.

But, Mac Yosemite Safari seems to interpret the rule by placing the top edge of the div at the center point, instead of centering the entire block. Not sure how to resolve and get a consistent display across all browsers.

Below is my source code.

<div class="row slh_featuredwrap hide-for-small">
  <div class="medium-12 columns">

      <div class="row" data-equalizer>
      <div class="medium-5 columns" data-equalizer-watch>

          <div class="slh_centerMeVertically"> <!--Section to be vertically centered compared to image in the right, medium-7 column-->
            <h3>TITLE</h3>
            <p>3-WORD DESCRIPTION</p>
          </div>

      </div>

      <div class="medium-7 columns" data-equalizer-watch>
        <img src=".../myImage.jpeg" /></a>
      </div>
      </div>

  </div>
</div>

<div class="row slh_featuredwrap show-for-small">
  <div class="medium-5 columns text-center">
    <h3>TITLE</h3>
    <p>3-WORD DESCRIPTION</p>
    </div>
  <div class="medium-7 columns">
    <img src=".../myImage.jpeg" /></a>
  </div>
</div>

Marc McGee over 2 years ago

Adding a couple more declarations to the rule seems to have fixed the issue for Safari.

New rule:

.slh_centerMeVertically {
  position: relative;
  top: 50%;
  -webkit-transform: translateY(-50%);
  -ms-transform: translateY(-50%);
  transform: translateY(-50%);
}

Robert Stark over 2 years ago

Hi Marc,

Thanks for pointing out the code issue - with smaller screens - I've updated it:

http://codepen.io/iamrobert/pen/RNqVmq

There seems to be an issue with some browsers being unable to re-size images when using "display: table":

http://stackoverflow.com/questions/11873706/responsive-images-in-a-fluid-width-table-max-width

So - the code below is working on my site but I am not using data-equalizer and I am yet to test extensively.

.valign-middle {
    display: table;
}

.valign-middle .columns {
    display: table-cell;
    vertical-align: middle;
}

.valign-middle .columns,
.valign-middle [class*="column"] + [class*="column"]:last-child {
    float: none;
}

/* medium and down images */
@media only screen and (max-width: 64.063em) {

  .valign-middle img {
    width: 100%;
      max-width: 100%;
}
}

@media only screen and (max-width:40.063em) {

.valign-middle .small-12.columns {
    display: block;
    vertical-align: top;
}  
}

Robert Stark over 2 years ago

My above example was having some issues with column ordering in Firefox.

So - if you use equalizer - then the height is set in the columns - so you can use the following below as you know the height :

http://codepen.io/iamrobert/pen/KwrRQB

/* VERTICAL CENTERING ---------------------- */
.out-vc {
  display: table;
}
.in-vc {
  display: table-cell;
  text-align: left;
  vertical-align: middle;
}

.in-vc-right {
  display: table-cell;
  text-align: right;
  vertical-align: middle;
}
          <div class="row collapse" data-equalizer>
  <div class="small-6 columns out-vc"  data-equalizer-watch><div class="in-vc">Text
</div></div>

  <div class="small-6 columns out-vc"  data-equalizer-watch><div class="in-vc">Text</div></div>

</div>