Centering HTML elements larger than their parents

It's not a common problem, but I've run into it a few times. How do you center an element when it is larger than it's parent? I mean really center it, where content overflows both the left and right borders of the parent element equally.

The default behaviour in HTML and CSS (using margin:0px auto;) is to line up the left edges of the child and parent elements while all the overflowing happens on the right side. That's not centered at all; it's most definitely offset to the right, which is painfully obvious if what you really wanted was to have the center of the child element line up with the center of the parent element, regardless of size.

Page centering context

This is the parent element

This is the child element
which should be centered

IMHO, the ideal behaviour would look something like this image:

So I was working on a project that required the behaviour I was expecting, rather than what HTML and CSS normally provides with a simple margin:0px auto; declaration. It also had to fit a few other strict criteria which ruled out several other "solutions" you can find out there.

  1. Has to work for children of varying widths, not just those of specified pixel dimensions.
  2. No absolute positioning or floating
  3. No JavaScript - The effect needed to work whether or not JavaScript was enabled or disabled.

Item #1 rules out the simplest solution which merely applies a negative left margin to the child element. If we know how wide the parent is, and how wide the child is, then we just need to apply a negative left margin that is equal to the difference of the child element and parent element widths, divided by two. If we don't know the width of the child element, setting a specific left margin is just going to make it look weird for all widths except one.

Item #2 rules out positioning solutions that use combinations of percentage positioning to achieve a centered child element. But because this removes the element from the flow of the document, the bottom of the parent element will cinch up and the content below it will collide with the content of the child element. I needed the parent element to remain tall enough to contain the height of the entire child element; it's only the width I was concerned about here.

Finally, Item #3 rules out JavaScript solutions that test the parent and child elements after the page has loaded and determines what negative margins or positioning values to set. This works every time, except if JavaScript is disabled. Granted that isn't often these days for visual browsers, but I still did not want to depend on script for something that was clearly just a styling issue.

Eventually I happened upon a solution that fit all three criteria above, and although it came with a few issues of its own, I decided I could live with them. You may know of a different or even better way to accomplish this, but here's what I came up with.

First, instead of setting a width or margins for the parent element wrt the page context, let it expand to the full width. Then relatively position it with a value of right:50%;.

Page centering context

This is the parent element

This is the child element
which should be centered

This puts the center of the parent element directly on the left border of the page centering context. Since the parent element is now the same width as the page centering context, that means its right border is exactly in the center of the page centering context! We exploit this fact as we move on.

What we want to do now is to move the center of the child element so it aligns with the right border of the parent element. In order to do this, the child element needs to be centered within the parent element so the center of the child element is also sitting on the left border of the page centering context.

Okay, leap-of-faith here: Even if it doesn't look like it's centered, as long as you apply the correct centering styles, the child element will behave as if it were centered when you apply the negative margins we'll need in the next step.

But we have a problem. How do you center a block if you need to specify both margin:0px auto; for centering and also a negative margin-right? Doing this will override one of the auto values of the margin and the child element will no longer be centered. Is there another way to center a block?

YES! We can use our old friend text-align:center; to center inline elements within the parent block. To make the style applicable to the block child element we are using, we'll turn it into a hybrid usingdisplay:inline-block;. This change introduces a restriction though, which prevents us from having other inline content abutting either side of the child element. Otherwise the text-align will not center our block properly. The child element needs to be the only inline element on the "line". So we'll have to remove our little "This is the parent element" note to move forward.

Page centering context

This is the child element
which should be centered

Like I mentioned before, it doesn't look centered, but its calculated position will behave as if it is when we apply the final step, the negative margin-right. With the parent block's left border resting in the center of the page centering context, we now know the distance between where the center of the child element is now, and where we need it to be: exactly half the width of the parent element.

This being said, you'd think a negative margin-right of 50% on the child element would move the center point nicely, but in fact it doesn't. Actually it only appears to move the block 25% of the width of the parent element.

Page centering context

This is the child element
which should be centered

This is indeed odd, and if someone knows why it behaves this way, I would be grateful to hear it explained. In any case, this oddity is no big deal to overcome; just specify a negative margin-right of 100% instead:

Page centering context

This is the child element
which should be centered

Centered! Now the only problem we're left with is the parent block; we don't want to see it. Hiding the parent block is simple, we'll just remove the border and make sure its background is transparent. We can't use display:none; or visibility:hidden; here because that would also affect the visibility of the child element.

Page centering context

This is the child element
which should be centered

And the code: (Important styles are highlighted)

div#context {
border:1px solid blue;
width:400px;
margin:0px auto;
}
div#context div {
position:relative;
right:50%;
text-align:center;
}
div#context div p {
border:1px solid green;
width:450px;
height:50px;
display:inline-block;
margin-right:-100%;
}

<div id="context">
Page centering context
<div>
<p>
This is the child element<br />
which should be centered
</p>
</div>
</div>

We're done! The great benefit of this system, despite the restrictions, is that it is uniquely dynamic. You can change the width of the child element to whatever you like and it will remain centered wrt the page centering context, either smaller or larger.

Page centering context

This is the child element
which should be centered

This is the child element
which should be centered

Things to remember about this system:

    1. The parent element can't contain any inline content that abuts the child inline-block.
    2. In fact, since the parent element is offset so, you probably can't use it for anything other than an empty non-visible container block for the child element.
    3. You can use left and margin-left to accomplish the same thing, although you run the risk of generating a horizontal scrollbar for the page.
    4. If the child element is an image, you don't need the display:inline-block; style, as images are already inline-blocks.
    5. IE7 and earlier can't inderstand the display:inline-block; style unless you apply it to an element that is inline by default (span, strong, em...). If you require compatibility for these browsers, use a<span> element for your child block.

http://www.greywyvern.com/?post=323

Centering HTML elements larger than their parents的更多相关文章

  1. Designing CSS Layouts With Flexbox Is As Easy As Pie

    This article is an updated excerpt of the chapter “Restyle, Recode, Reimagine With CSS3″ from our Sm ...

  2. uva 10723

      10723 - Cyborg Genes Time limit: 3.000 seconds Problem F Cyborg Genes Time Limit 1 Second Septembe ...

  3. [LeetCode#84]Largest Rectangle in Histogram

    Problem: Given n non-negative integers representing the histogram's bar height where the width of ea ...

  4. The algorithm learning of sort which include Bubblesort,Insertsort,Quicksort and Mergesort.

    Notice : these algorithms achieved by Java. So,let's going to it. firstly, what is Bubblesort? why w ...

  5. way.js

    (function (root, factory) { if (typeof define === "function" && define.amd) { defi ...

  6. phpquery 学习笔记

    phpQuery是一个基于PHP的服务端开源项目,它可以让PHP开发人员轻松处理DOM文档内容,比如获取某新闻网站的头条信息.更有意思的是,它采用了jQuery的思想,你可以像使用jQuery一样处理 ...

  7. 10723 Cyborg Genes (LCS + 记忆化搜索)

    Problem F Cyborg Genes Time Limit 1 Second September 11, 2132. This is the day that marks the beginn ...

  8. Leetcode: Max Sum of Rectangle No Larger Than K

    Given a non-empty 2D matrix matrix and an integer k, find the max sum of a rectangle in the matrix s ...

  9. jsoup的elements类

    jsoup的Elements类 一.简介 该类是位于select包下,直接继承自Object,所有实现的接口有Cloneable, Iterable<Element>, Collectio ...

随机推荐

  1. tcpdump抓包

    名称(NAME)tcpdump-转储网络上的数据流总览(SYNOPSIS)tcpdump[-adeflnNOpqStvx][-ccount][-Ffile] [-iinterface][-rfile] ...

  2. JAVA设计模式--State(状态模式)

    状态模式(State Pattern)是设计模式的一种,属于行为模式. 定义(源于Design Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 状态模式主要 ...

  3. 打地鼠游戏ios源码

    打地鼠游戏源码,游戏是一款多关卡基于cocos2d的iPad打地鼠游戏源码,这也是一款高质量的打地鼠游戏源码,可以拥有逐步上升的关卡的设置,大家可以在关卡时设置一些商业化的模式来盈利的,非常完美的一款 ...

  4. POJ C++程序设计 编程题#1 编程作业—运算符重载

    编程题 #2 来源: POJ (Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩.) 注意: 总时间限制: 1000ms 内存限制: 65536kB 描述 下面的MyIn ...

  5. POJ C++程序设计 编程作业—类和对象 编程题#3

    编程题 #3 来源: POJ (Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩.) 注意: 总时间限制: 1000ms 内存限制: 65536kB 描述 下面程序的输出 ...

  6. Clearing Search Values

      Use the SearchClear() method which is part of the Field class to clear search values on a particul ...

  7. [原]Django调试工具--django-debug-toolbar

    请摒弃简单粗暴的print --马云 我比较习惯在windows中安装pycharm开发,项目部署在虚拟机中,在本地浏览器中查看效果,这种方式在调试上会有点麻烦,django-debug-toolba ...

  8. javascript变量和对象要注意的点

    js对象和变量,对象本身是没有名称的,之所以使用变量是为了通过某个名称来称呼这样一种不具名称的对象.变量分基本变量和引用类型变量.将基本类型的的值付给变量的话,变量将这个值本身保存起来. <sc ...

  9. 2013-10-25笔记,css: mini-width, 标准居中,样式中*号使用,背景图像位置定位

    mini-width:设置元素的最小宽度.該屬性值會對元素的寬度設置一個最小限制.因此,元素可以比制定值寬,但不能比制定值窄.不允許指定負值. 完美的居中佈局: body{text-align: ce ...

  10. C++列出完数

    题目内容:自然数中,完数寥若晨星,请在从1到某个整数范围中打印出所有的完数来.所谓“完数”是指一个数恰好等于它的所有不同因子之和.例如,6是完数,因为6=1+2+3.而24不是完数,因为24≠1+2+ ...