9

I would like to achieve a layout that looks like this:

Inner div nested in Outer div with equal margins for top, left, and right.

I am interested in a css/html only solution, so no javascript required.

The widths of both divs are dynamic, so I cannot use any static margins.

The spacing between the sides of the divs, and the top, should be the same.

I tried using margin: auto auto 0 auto on the inner div, as you can see in this jsfiddle, but it only works for left and right.

V Maharajh
  • 9,013
  • 5
  • 30
  • 31
  • I don't think this is possible to do with just html and css. But you could certainly do it with javascript (although you would need to keep track of when the size(s) change yourself, since there isn't a resize event on individual elements). – Thayne Apr 30 '15 at 00:35
  • @sdcr, sure, if you can solve the problem with a fixed height assumption, I'd love to see it – V Maharajh Apr 30 '15 at 00:38

6 Answers6

6

Note, the following attempt doesn't answer the question fully, since the width of the child cannot be dynamic.

The idea is to use a percentage width + percentage margin-top values on the child. It's a responsive layout, see the comments in the code, and try it out on different window sizes.

JSFiddle: http://jsfiddle.net/jkoycs6e/

body {
    margin: 0;
}
.outer {
    height: 100vh; /*for demo only*/
    background: teal;
    overflow: auto;
}
.inner {
    width: 80%;
    background: gold;
    margin: auto;
    margin-top: 10%; /* 100%-80%/2 */
}
<div class="outer">
    <div class="inner">
        hello<br/>hello<br/>hello
    </div>
</div>
Stickers
  • 75,527
  • 23
  • 147
  • 186
  • closest thing to an answer, but you're right, this still won't work for me since the widths are completely dynamic. Thanks though, I had always assumed that margin-top as a % would be relative to the *height*, but it actually applies to *width*. – V Maharajh Apr 30 '15 at 15:45
  • 1
    @vivekmaharajh that's correct margin and padding are always relative to the parents' width, not height. I really doubt if it's possible to fully answer it with pure css, but good luck. – Stickers Apr 30 '15 at 15:48
2

This is not possible. At least not without using javascript. There is no css-only solution.

V Maharajh
  • 9,013
  • 5
  • 30
  • 31
1

If you put align="center" in your div you'll get to the middle of the screen every time but it's not going to be supported in HTML5 so I recommend the 50:50 approach.

div
{
 text-align:center;
 margin-top:50%;
 margin-bottom:50%;
}

Hope that helps. ^^

The Pademelon
  • 835
  • 11
  • 29
  • Sorry, I'm not trying to center the inner div vertically. I'm trying to center it horizontally only, and then move it to the top of the outer div (plus the margin that was needed to center it on the sides). See my image above, it is not centered vertically. – V Maharajh Apr 29 '15 at 23:50
  • I've been reading [this](http://www.thecodingforums.com/threads/set-css-property-equal-to-another-css-property.159651/) article and basically what you're trying to do is impossible with just CSS and HTML. – The Pademelon Apr 30 '15 at 00:16
0

Set the outer parent's overflow to auto and give your margin-top a relative value. Something like this:

.outer {
    background: blue;
    overflow: auto;
}
.inner {
    background:yellow;
    width: 100px;
    height: 100px;
    margin: 1em auto 0 auto;
}
<div class="outer">
    <div class="inner">
    </div>
</div>
0

This seems to work:

.outer {
    height: 500px;
    width: 300px;
    background: blue;
    position: relative;
}

.inner {
    width: 80%;
    height: 200px;
    background:green;
    position: absolute;
    margin-left: 10%;
    margin-right: 10%;
    margin-top: 10%;
    margin-bottom: 0;
}

You can change the percentages marked for the margins as per your intended value for k.

Here's the fiddle

EDIT: Note that the width of inner has to be set in terms of percentages for this to work. Also note that when a margin is specified in terms of percentage, the margin's value is computed as a percentage of the width of the container. Even for the vertical margins, the percentage is applied on the width (and NOT the height) of the container.

Here's an SO post that's helpful in understanding how to position elements with respect to their container.

Community
  • 1
  • 1
jithinpt
  • 1,204
  • 2
  • 16
  • 33
  • Sorry, I can't use this. Note that in my question I stated that the widths of outer and inner are dynamic and unknown. – V Maharajh Apr 30 '15 at 00:30
  • But once you fix (a) the width of outer and (b) the value of k (for the margins), that automatically implies that the width of inner has been fixed to a percentage of the width of outer. This is the reason, the width of inner needs to be a percentage – jithinpt Apr 30 '15 at 00:34
  • There are 3 parameters here: (i) Width of outer (ii) Width of inner and (iii) k. Once you fix two of them, the third one is then automatically fixed to a certain value. – jithinpt Apr 30 '15 at 00:35
  • I'm unable to fix (i) or (ii), because i'm working on a responsive design in which the width's of the elements changes as the page is resized. – V Maharajh Apr 30 '15 at 00:39
  • 1
    Ok. In that case, I guess you would need to use javascript. Because I don't think CSS provides a way to specify the top margin with respect to the left and right margins. – jithinpt Apr 30 '15 at 00:42
  • unfortunately, that seems to be the consensus so far. thanks for looking into this with me. – V Maharajh Apr 30 '15 at 00:47
0

This answer doesn't actually make use of the margin property, nor does it have only two div.

body {
    font-size: 26px;
    text-align: center;
    font-family: monospace;
  }


  #container {
    display: inline-block;
    position: relative;
    width: 100%;
  }

  #dummy {
    margin-top: 20%;
  }

  #element {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background-color: silver
    /* show me! */
  }

  #wrapper {
    display: table;
    width: 100%;
  }

  #row {
    display: table-header-group;
  }

  #left {
    display: table-cell;
    background-color: chartreuse;
    width: 20%;
  }

  #incenter {
    display: table-cell;
    background-color: aqua;
  }

  #right {
    display: table-cell;
    background-color: chartreuse;
    width: 20%;
  }
<div>
    <div id="container">
      <div id="dummy"></div>
      <div id="element">
        k (20%)
      </div>
    </div>
    <div id="wrapper">
      <div id="row">
        <div id="left">width = k (20%)</div>
        <div id="incenter">incenter</div>
        <div id="right">width = k (20%)</div>
      </div>
    </div>
  </div>

Another example with measurements in pixels is here.

For explanation refer:

https://stackoverflow.com/a/12121309/2534513

https://stackoverflow.com/a/6615994/2534513

I have actually combined techniques mentioned in above two answers to make this one. Using JavaScript would have been a lot easier.

Community
  • 1
  • 1
Ashesh
  • 3,499
  • 1
  • 27
  • 44
  • It looks like you've achieved the same thing @sdcr did in his answer. The problem with this is that it assumes the width of the inner div is fixed to 60% of the outer div. In my question, you'll see that the widths are independent and dynamic. – V Maharajh Apr 30 '15 at 18:13
  • yeah inner div will be 60% of the total width available, but I am pretty sure it can be tweaked further, seen the JSFiddle link I included? – Ashesh Apr 30 '15 at 19:02