ChatGPT解决这个技术问题 Extra ChatGPT

Why is vertical-align: middle not working on my span or div?

I'm trying to vertically center a span or div element within another div element. However when I put vertical-align: middle, nothing happens. I've tried changing the display properties of both elements, and nothing seems to work.

This is what I'm currently doing in my webpage:

.main { height: 72px; vertical-align: middle; border: 1px solid black; padding: 2px; } .inner { vertical-align: middle; border: 1px solid red; } .second { border: 1px solid blue; }

This box should be centered in the larger box
Another box in here

Here is a jsfiddle of the implementation showing that it doesn't work: http://jsfiddle.net/gZXWC/


e
ethry

This seems to be the best way - some time has passed since my original post and this is what should be done now:

.main { display: table; /* optional css start */ height: 90px; width: 90px; /* optional css end */ } .inner { border: 1px solid #000000; display: table-cell; vertical-align: middle; }

This


So how does someone do what the OP wants to do?
Any ideas on variable line paragraphs? ie. if there is no way of knowing whether it will be one or two lines. Would I need to user jQuery then?
What if the height must be dynamic, what is the solution?
shouldn't be the accepted answer, relies on knowing height of '.inner', so not exactly what the OP was asking for and some much better answers below see @timbergus or Tim Perkins' answers way down near the bottom.
@Sauce works fine for me when setting a fixed height. If you noticed, the jsfiddle that's attached here is not the current solution provided. My guess is you clicked the JSFiddle, rather than actually using the code.
D
Dinesh Kumar

Using CSS3:

<div class="outer">
   <div class="inner"/>
</div>

Css:

.outer {
  display : flex;
  align-items : center;
}

use "justify-content: center;" to align elements horizontally

Note: This might not work in old IE's


This is supported by all major modern browsers and by the simplest and cleanest solution.
Also keep in mind inline-flex to have multiple elements in a row inside the inner element.
In my case, since I wanted to center the content of .inner horizontally too, I had to add .inner { width: 100%; }. This way, it seems to work like .outer { display: table; } .inner { display: table-cell; vertical-align: middle; } but without forcing a minimum width.
I used justify-content: center; to align horizontally which worked great
wkhtmltopdf doesn't support flex
M
Mahendra Liya

Try this, works for me very well:

/* Internet Explorer 10 */
display:-ms-flexbox;
-ms-flex-pack:center;
-ms-flex-align:center;

/* Firefox */
display:-moz-box;
-moz-box-pack:center;
-moz-box-align:center;

/* Safari, Opera, and Chrome */
display:-webkit-box;
-webkit-box-pack:center;
-webkit-box-align:center;

/* W3C */
display:box;
box-pack:center;
box-align:center;

excellent answer, this has given me a fully working solution that hasn't caused other knock-on issues (an app using jquerymobile + phonegap and all the other solutions led to css & div sizing issues). Just to point out that these parameters have to be added to a CSS block specific to the elements to be centred/middled, eg: #element span {height:100%;display:-webkit-box;-webkit-box-pack:center;-webkit-box-align:center;} - note the height is important to ensure the span inherits the full height of its container (probably a div) otherwise you still won't get vertical centering!
BTW, you can write standard flexbox code without browser prefixes and then get browser prefixed with autoprefixer github.com/postcss/autoprefixer or via online demo simevidas.jsbin.com/gufoko/quiet
invalid property value box in display
Also, @user1782556's answer works better when the outer box has padding.
K
Kevin Lynch

Setting the line-height to the same height as it's containing div will also work

DEMO http://jsfiddle.net/kevinPHPkevin/gZXWC/7/

.inner {
    line-height:72px;
    border: 1px solid #000000;
}

I posted a link that explained that method as well. Not my prefered method though, if the rest of the layout is not fixed in size - I have run into issues on different sized viewports with this method.
yes the line-height technique works well, but ONLY IF you have single-line content. Additional lines will be lost / will spill outside the container and you'll need to start again!
a) line-height will also change the height of the inner element. b) The inner element is still not accurately vertically centered. c) It does not work on elements that do not contain text, for ex: <img>, or elements with fixed height.
It can also fail cross-OS (Windows/Mac) due to font-rendering differences
This is very unpredictable and often results in extra height on the container.
k
kornieff

In case you cannot rely on flexbox... Place .child into .parent's center. Works when pixel sizes are unknown (in other words, always) and no problems with IE9+ too.

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


This is actually the most well done solution, especially since most projects I've seen so far need IE9 compatibility
I like this solution, but it shrinks my content by 50%? How do I avoid that?
EDIT: Found my solution, I used the solution above and added width: 80% to fit my image content into the container.
V
VLAZ

You should put vertical-align: middle on the inner element, not the outer element. Set the line-height property on the outer element to match the height of the outer element. Then set display: inline-block and line-height: normal on the inner element. By doing this, the text on the inner element will wrap with a normal line-height. Works in Chrome, Firefox, Safari, and IE 8+

.main { height: 72px; line-height:72px; border: 1px solid black; } .inner { display: inline-block; vertical-align: middle; line-height: normal; }

Vertically centered text

Fiddle


This is probably the simplest way... all other answers on this page are unnecessarily clunky/hacky OR not supported in older browsers OR rely on knowing the height of the inner element. You don't actually need the line-height: normal; and display:inline; works too. The bonus of this method is it doesn't interfere with text-align:center;, which using display: table-cell; can create issues with. Quite often we want to align horizontally as well as vertically. See this edited fiddle: jsfiddle.net/br090prs/36
@mike-source the reason to use line-height: normal and display: inline-block is so that the inner text will wrap properly. If you're sure that the text in the inner div will never wrap then these properties won't be necessary.
Ever since Microsoft ended support for old versions of IE I have used flexbox for this sort of thing (as @user1782556 suggested). My original answer is the way to go if you still need to support IE 10 or older.
100% agree, but I wouldn't personally go for flex box just yet, only 76% of browsers fully support it as of May 2016 (94% if you include partial support), see: caniuse.com/#search=flexible%20box. It is getting very close to being the most sensible option though, depending on your user base.
vertical-align: middle has (almost) no effect here. It is the line-height that positions the .inner in the middle.
R
Ruth Young

I used this to align everything in the center of the wrapper div in case it helps anyone - I found it simplest:

div.wrapper { /* --- This works --- */ display: flex; /* Align Vertically */ align-items: center; /* Align Horizontally */ justify-content: center; /* --- ---------- ----- */ width: 100%; height:100px; background-color: blue; } div.inner { width: 50px; height: 50px; background-color: orange; }


k
king

This is a modern approach and it utilizes the CSS Flexbox functionality. You can now vertically align the content within your parent container by just adding these styles to the .main container

.main {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center; // To center align it horizontally as well
}

You can also use CSS Grids ( a two-dimensional grid-based layout system).

.main {
  display: grid;
  justify-content: center;
  align-content: center;
}

Below is a Shorthand approach but browser support is still low - https://caniuse.com/?search=place-items.

    .main {
      display: grid; // flex  -  works for both
      place-items: center;
    }

And you are good to go!


T
Timbergus

Here you have an example of two ways of doing a vertical alignment. I use them and they work pretty well. One is using absolute positioning and the other using flexbox.

Vertical Align Example

Using flexbox, you can align an element by itself inside another element with display: flex; using align-self. If you need to align it also horizontally, you can use align-items and justify-content in the container.

If you don't want to use flexbox, you can use the position property. If you make the container relative and the content absolute, the content will be able to move freely inside the container. So if you use top: 0; and left: 0; in the content, it will be positioned at the top left corner of the container.

https://i.stack.imgur.com/y9A5I.png

Then, to align it, you just need to change the top and left references to 50%. This will position the content at the container center from the top left corner of the content.

https://i.stack.imgur.com/hjAXM.png

So you need to correct this translating the content half its size to the left and top.

https://i.stack.imgur.com/p63HE.png


B
Brijesh Patel

HTML

<div id="myparent">
  <div id="mychild">Test Content here</div>
</div>

CSS

#myparent {
  display: table;
}
#mychild {
  display: table-cell;
  vertical-align: middle;
}

We set the parent div to display as a table and the child div to display as a table-cell. We can then use vertical-align on the child div and set its value to middle. Anything inside this child div will be vertically centered.


A
Alexis Wilke

here is a great article of how to vetical align.. I like the float way.

http://www.vanseodesign.com/css/vertical-centering/

The HTML:

<div id="main">
    <div id="floater"></div>
    <div id="inner">Content here</div>
</div>

And the corresponding style:

#main {
   height: 250px;
}

#floater {
   float: left;
   height: 50%;
   width: 100%;
   margin-bottom: -50px;
}

#inner {
   clear: both;
   height: 100px;
}

I think that if you define the height of the #inner block it invalidates the concept of proper vertical centering. The OPS was asking to make it automatic, so I would imagine that means the height of the inner box is not known at conception time.
S
Sнаđошƒаӽ

It's simple. Just add display:table-cell in your main class.

.main {
  height: 72px;
  vertical-align: middle;
  display:table-cell;
  border: 1px solid #000000;
}

Check out this jsfiddle!


D
Downhillski

Here is the latest simplest solution - no need to change anything, just add three lines of CSS rules to your container of the div where you wish to center at. I love Flex Box #LoveFlexBox

.main { /* I changed height to 200px to make it easy to see the alignment. */ height: 200px; vertical-align: middle; border: 1px solid #000000; padding: 2px; /* Just add the following three rules to the container of which you want to center at. */ display: flex; flex-direction: column; justify-content: center; /* This is true vertical center, no math needed. */ } .inner { border: 1px solid #000000; } .second { border: 1px solid #000000; }

This box should be centered in the larger box
Another box in here
This box should be centered in the larger box
Another box in here

Bonus

the justify-content value can be set to the following few options:

flex-start, which will align the child div to where the flex flow starts in its parent container. In this case, it will stay on top.

center, which will align the child div to the center of its parent container. This is really neat, because you don't need to add an additional div to wrap around all children to put the wrapper in a parent container to center the children. Because of that, this is the true vertical center (in the column flex-direction. similarly, if you change the flow-direction to row, it will become horizontally centered.

flex-end, which will align the child div to where the flex flow ends in its parent container. In this case, it will move to bottom.

space-between, which will spread all children from the beginning of the flow to the end of the flow. If the demo, I added another child div, to show they are spread out.

space-around, similar to space-between, but with half of the space in the beginning and end of the flow.


Perfect solution. The incompatible browsers can take the content unaligned and the user must deal with it or upgrade his/her browser.
R
Rahul Daksh

set below CSS

 /*Parent*/
 display: table;

/*immediate child*/
display: table-cell;
vertical-align: middle;

~Rahul Daksh


S
Smig

Since vertical-align works as expected on a td, you could put a single celled table in the div to align its content.

<div>
    <table style="width: 100%; height: 100%;"><tr><td style="vertical-align: middle; text-align: center">
        Aligned content here...
    </td></tr></table>
</div>

Clunky, but works as far as I can tell. It might not have the drawbacks of the other workarounds.


No, please, no tables anymore. CSS can do that in a clean way. There's no need to use in this case.
R
Ramiro Mosquera

Just put the content inside a table with height 100%, and set the height for the main div

<div style="height:80px;border: 1px solid #000000;">
<table style="height:100%">
<tr><td style="vertical-align: middle;">
  This paragraph should be centered in the larger box
</td></tr>
</table>
</div>

P
Paul Rooney

To vertically center a span or div element within another div, add position relative to parent div and position absolute to the child div.Now the child div can be positioned anywhere inside the div.Example below centers both horizontally and vertically.

<div class="parent">
    <div class="child">Vertically and horizontally centered child div</div>
</div>

css:

.parent{
    position: relative;
}
.child{
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
}