Vertical align or flex box

Hi,

In the code below I have two divs with a class of .hp-tips. Within those two divs is an h6, a p and an img tag. I’m using css to absolutely position the image relative to the .hp-tips parent div. I need to vertically align the h6 and the p tag within the parent div so that there is equal space above the h6 and below the p tag.

As you can see in the code I tried to use “vertical-align: middle” on the first div but this had no effect - the h6 and p still remain at the top. I’m not sure whether I should be using vertical align or flex box.

I just wondered if someone could tell me how I could make this work?

Appreciate any advice.

 <div class="row justify-content-end">
     
    <div class="col-sm-12 col-md-3 offset-md-5 rounded-top hp-tips" style="vertical-align: middle;">

      <h6 class="text-uppercase">Heading</h6>
          <p>Text will go here. Some more here.</p>
          <img id="left" src="images/content/image1.png"> 
          </div>
  
    <div class="col-sm-12 col-md-3 ml-sm-3 rounded-top hp-tips">
      <h6 class="text-uppercase">Heading</h6>
          <p>Text will go here. Some more here.</p>
          <img src="images/content/image3.png">
      </div>
      
  </div>

  </div>

That’s because they are block elements. vertical-align applies to inline elements, html tables, and display:table

Thanks for the info Ray. So is there a way to do vertical align using flexbox?

Yes align-items:center on the element with display:flex will align its flex items vertically. That means that the immediate children will be centered and not necessarily the grand children of nested containers.

I’m not on a computer to test at the moment but it looks you need to set display:flex and align-items:center on the columns themselves in order to center the content within a column and not the column itself.

You would then need to set flex:1 0 100% on the immediate children so that they stretch full width.

Of course this also depends on what margins you have on the elements as that is counted in the centering.

If you are absolutely placing the image then that is discounted from any flow effect at all and will not take place on centering or sizing the parent. It’s hard to tell from your snippet what is creating the height that you want elements to be centered within. We may need to see a working example to debug properly.

Have a try and see if you can accomplish this yourself if not I’ll be back later in the day. :slight_smile:

Thanks for the info Paul. In the code below, I added the bootstrap classes for display:flex and align-items:center to one of the columns in order to test. I also added flex:1 0 100% to the h6 and p tag which were the immediate children. When I test it, the h6 is correctly vertically centred but the p was in a column to the right and outside the containing div.

Are you able to show me how this could work with an example or do you know if I can adjust the code to make the p vertically centered like the h6?

    <div class="col-sm-12 col-md-3 offset-md-5 rounded-top hp-tips d-flex align-items-center" style="vertical-align: middle;">

      <h6 class="text-uppercase" style="flex: 1 0 100%;">Heading</h6>
          <p style="flex: 1 0 100%;">Text will go here. Some more here.</p>
          <img id="left" src="images/content/image1.png"> 
          </div>

You also need to set flex-wrap:wrap on the element that has display:flex or else it won’t wrap :slight_smile:

I’ll give you a demo later this afternoon as still out at the moment and on a mobile :slight_smile:

It’s hard to tell form your code what type of vertical alignment you are expecting and what dictates the height of the element. You seem to have just one column in the centre but its height is only content height so there is indeed nothing to centre.

If perhaps you have a min-height or something on the column then you could use the flex classes from bootstrap like this.

 <div class="col-sm-12 col-md-3 offset-md-5 rounded-top hp-tips d-flex justify-content-center flex-column flex-wrap">
      <h6 class="text-uppercase">Heading</h6>
      <p>Text will go here. Some more here.</p>
      <img class="left" src="images/content/image1.png"> </div>

It’s impossible for me to give a firm answer without seeing an example of all the code involved and knowing what the requirement is supposed to be. The absolutely placed image could also be a worry as I don;t know what you are trying to do there?

I’m back home now for a few hours if you get back to me I’ll take another look.

Thanks again. Here is a code pen example of what I’m trying to do:

https://codepen.io/gwnh/pen/38c9a0e4fe72a0626dcdb5061ba5a7b3

You’ll notice that the left div block has more text in it than the right one. I thought that if I used flex to align the child elements vertically then both would remain centred even though the amount of text would vary.

Also, the section containing the layout has a height of 50vh and it contains 2 bootstrap rows. I applied align-items-end to the section element which has positioned both rows at the end of the section. This is ok for the second row as I want the two green divs to always remain at the bottom of the section, but it’s not working for the first row with the h1 text. I need this first row to stretch so that the text is always vertically centred in the area above the green boxes. I tried to do this by applying align-items-center to the first row but this didn’t work.

If you could help me to get this work, I’d really appreciate it.

Sorry I missed your post last night I’ll take a look when I get back home later this afternoon :slight_smile:

Great - thanks so much

It’s quite awkward to do this with bootstrap as the structure is all wrong but the following should work after a fashion :slight_smile:

<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://uploads.prod01.sydney.platformos.com/instances/17/assets/modules/siteglide_design_system/css/bootstrap/bootstrap.min.css?updated=1568365883">
<link rel="stylesheet" href="https://uploads.prod01.sydney.platformos.com/instances/17/assets/modules/siteglide_design_system/css/main.min.css?updated=1568365882">
<link rel="stylesheet" href="https://uploads.prod01.sydney.platformos.com/instances/17/assets/css/modules/module_9/custom.css?updated=1571870783">
</head>
<body>
<header class="header header-03 bg-dark">
  <nav class="navbar navbar-expand-lg navbar-dark">
    <div class="container"> <a class="navbar-brand" href="#" title=""> <img src="https://uploads.prod01.sydney.platformos.com/instances/17/assets/" alt=""> </a>
      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button>
      <div class="collapse navbar-collapse" id="navbarNav">
        <ul class="navbar-nav d-flex-lg align-items-lg-center">
          <li class="nav-item"> <a class="nav-link" href="#" title="">Item 1</a> </li>
          <li class="nav-item"> <a class="nav-link" href="#" title="">Item 1</a> </li>
          <li class="nav-item"> <a class="nav-link" href="#" title="">Item 1</a> </li>
          <li class="nav-item"> <a class="nav-link" href="#" title="">Item 1</a> </li>
        </ul>
      </div>
    </div>
  </nav>
</header>
<section class="d-flex  background-image" style="background-color: grey; min-height: 50vh;">
  <div class="container" style="flex:1 0 100%;display:flex;flex-direction:column">
    <div class="row align-items-center justify-content-end hp-hero-row" style="text-align: right;margin-top:auto;" >
      <div class="col-md-6 xhp-hero-text">
        <h1>Lorem ipsum  sit amet, consectetur adipiscing elit.</h1>
      </div>
    </div>
    <div class="row justify-content-end" style="margin-top:auto;">
      <div class="col-sm-12 col-md-3 offset-md-5 rounded-top hp-tips d-flex flex-wrap align-content-center">
        <h6 class="text-uppercase" style="flex: 1 0 100%;">HEADING</h6>
        <p style="flex: 1 0 100%;">This left div block has more text in it than the right one.This left div block has more text in it than the right one..</p>
        <img class="left" src="https://uploads.prod01.sydney.platformos.com/instances/17/assets/images/content/food-plate.png?updated=1570342940"> </div>
      <div class="col-sm-12 col-md-3 ml-sm-4 rounded-top hp-tips d-flex  flex-wrap align-content-center">
        <h6 class="text-uppercase" style="flex: 1 0 100%;">HEADING</h6>
        <p style="flex: 1 0 100%;">This is where the text will go. More text here.</p>
        <img class="left" src="https://uploads.prod01.sydney.platformos.com/instances/17/assets/images/content/food-plate.png?updated=1570342940"> </div>
    </div>
  </div>
</section>
</body>
</html>

Note that you don’t want a fixed 50vh height on that section because that will break all the content if the text is zoomed or on smaller windows when text wraps. Instead use min-height not height.

Although I have added the css in the inline style attribute I have only done that because you already started doing that.:slight_smile: Before you put this into production you should remove the inline styling and use classes combined with external css as usual.

Thanks so much for this Paul. You mentioned that you thought it was awkward to do this with bootstrap as the structure is wrong so I’d be interested to know your thoughts on bootstrap in general. I noticed that it uses a lot of divs which I know is not best practice so I was just wondering if you think it’s a good framework to use or is it only okay with certain layouts?

I’m using bootstrap for the whole page but for this particular section, could I have used bootstrap for the grid section, ie. to layout the main elements and then use regular css to absolutely position those two green boxes at the bottom instead of putting them in a separate bootstrap row/column? I mean would that have been a better structure?

I’m just trying to improve my css skills and would like to know best practices so it would be good to know your thoughts.

No absolute position should be avoided for structural content as it removes the items from the flow and leaves you nothing to react against. The most important thing about any design is maintaining a flow where one element reacts with another so that you are not relying on magic numbers to create the effect you want.

Flexbox is ideal for what you want but the bootstrap structure is a little convoluted especially in the way you have applied it. I would have come out of bootstrap and written my own code for that section but then of course you have to build in all the media queries and other refinements.

Ignoring bootstrap for the moment the structure you would have needed for that is as simple as this.

https://codepen.io/paulobrien/full/RwwVqeG

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Untitled Document</title>
<style>
html {
	box-sizing: border-box;
}
*, *:before, *:after {
	box-sizing: inherit;
}
html, body {
	margin:0;
	padding:0;
}
.fluid-container {
	background-color: grey;
}
.sub-header {
	max-width:1170px;
	margin:auto;
	display:flex;
	flex-direction:column;
	min-height: 50vh;
}
.base {
	display:flex;
	justify-content:flex-end;
}
.left-block, .right-block {
	width:25%;
	margin-left:5%;
	background:#118079;
	padding:1rem;
}
.sub-header h1{
	width:55%;
	padding:1rem;
	font-size:40px;
	text-align:right;
	background:#f9f9f9;
	margin:auto 0 auto auto;
}
@media screen and (max-width:767px){
	.left-block, .right-block,.sub-header h1 {width:100%;}

}
</style>
</head>

<body>
<div class="fluid-container">
  <section class="sub-header">
    <h1>Lorem ipsum  sit amet, consectetur adipiscing elit.</h1>
    <div class="base">
      <div class="left-block">
        <h2>Heading</h2>
        <p>This left div block has more text in it than the right one.This left div block has more text in it than the right one..</p>
      </div>
      <div class="right-block">
        <h2>Heading</h2>
        <p>This is where the text will go. More text here.</p>
      </div>
    </div>
  </section>
</div>
</body>
</html>

That’s just a rough idea but as you can see the code is much simplified and easier to manage.

There’s no reason why you can’t write your own sections when you have something awkward but you still must follow the bootstrap guidelines on your page construction.

Bootstrap comes with a lot of good stuff but is generally overkill for small sites but some people do love it. However you do need to become skilled in both bootstrap and CSS. there are no short-cuts.

Also try to use best html practices and use headings in a logical manner. You can’t go straight from an h1 to an h6 as that will corrupt the document outline and confuse assistive devices.

1 Like

Thanks for explaining this - I thought that if I was using bootstrap for a site then I had to stick with it for the entire code. I didn’t know I could break out of it for a section.

There’s no reason why you can’t write your own sections when you have something awkward but you still must follow the bootstrap guidelines on your page construction.

Regarding following the bootstrap guidelines on the page construction, do you mean I need to stick with their class names? Could you clarify this?

What I mean is that if you use a .row element (which must be inside a container element) then the next element must be a col element as per the grid. However there’s no reason that you can’t close the bootstrap container and start your own section not under the influence of the bootstrap grid

In the end you can do what you like as long as you understand how bootstrap works. the rows and columns work together by using padding on one and negative margins on the other to create the gutters and spacing. If you omit one or the other you break the grid. However if you know how it works you can write your own fixes.:slight_smile:

Ok I see what you mean now - I may even use the simpler code for the section I’m working on now that I understand it all a bit better.

Thanks again for your advice.

Hi Paul,

Sorry to come back to this post, but I’ve used the the bootstrap layout that you provided for now. The h1 text works well on tablets and desktop devices and vertically centres correctly but I’ve found that on mobile phones it doesn’t vertically centre, ie. there is no space above the h1 - only below it.

Is there a reason why the margin-top:auto isn’t being applied on smaller mobile devices and not centring the text?

Thanks again for your help.

I think you will need to show a screenshot of what you see as the h1 will be centered vertically assuming there is room for it to do so.

You have set the area concerned to be a min-height of 50vh which likely means that on a small device the content is already greater than 50vh and therefore there is nothing to center as all the space was used up.

Maybe you need to increase the 50vh to 100vh on small screens in your media query but i;m not sure what effect you are trying to do exactly :slight_smile:

I am away on holiday for 2 weeks so it may take me a little while to respond as I only check in once a day while away. :wink:

Thanks for replying Paul. I worked out what the problem was - I had an image below the h1 and as it was too large on mobile phones it looked like it was centring. I used a media query to scale down the image on smaller devices.

Thanks again

2 Likes