Forum Moderators: not2easy

Message Too Old, No Replies

A float / positioning problem

         

asterickx

2:04 pm on Dec 3, 2014 (gmt 0)

10+ Year Member



Hi guys,

(I'm not a native English speaker, so please bear with me.)

I'm converting a table-based layout to tableless (html5 + css3), and I have difficulties with the following layout:


-----------------
| 1 | 2 | 3 | 4 |
-----------------
| 5 |///////| 6 |
----|///X///|----
| 7 |///////| 8 |
-----------------
| 9 | 10| 11| 12|
-----------------


Short description: one big square (container div) containing an UL with 12 LI items (numbered 1 to 12 in the drawing above).

Problem: I can easily float all 12 boxes, but I can't have a box in the X area (let's call it "X box") using just float. I can set a background image for the X area by using background-image for the containing div, but it has to be an individual image file (no sprite) and I can't have any content in the X area.

Alternatively, I managed to set up an X box absolutely positioned (relative to the container div) where I can put content or I can have a sprite background - and I'm pretty satisfied with this soluton.

Question 1: is there a way to achieve a layout with all 13 boxes (1-12 plus the X box) using just float and clear (i.e with 13 LI items in the UL)?

Question 2: do you see a better solution than 12 floats + 1 absolutely positioned div?

Many thanks in advance.

--
Asterickx

[edited by: asterickx at 2:37 pm (utc) on Dec 3, 2014]

asterickx

2:13 pm on Dec 3, 2014 (gmt 0)

10+ Year Member



Trying a better drawing using "fixed":


-----------------
| 1 | 2 | 3 | 4 |
-----------------
| 5 |///////| 6 |
----|///X///|----
| 7 |///////| 8 |
-----------------
| 9 | 10| 11| 12|
-----------------

Fotiman

3:51 pm on Dec 3, 2014 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Welcome to WebmasterWorld! Great question, and nice diagram to describe the problem.

Would it be an option to have, essentially, some spacer items between box 5 and 6, and between 7 and 8? For example:


-----------------
| 1 | 2 | 3 | 4 |
-----------------
| 5 | space | 6 |
----|-------|----
| 7 | space | 8 |
-----------------
| 9 | 10| 11| 12|
-----------------

And then just position the X box on top of that space area? For example:

<div class="container">
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li class="spacer">&nbsp;</li>
<li>6</li>
<li>7</li>
<li class="spacer">&nbsp;</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
</ul>
<div class="X">X</div>
</div>


.container {
/* Relatively positioned so X will be positioned from top left of container */
position: relative;
}

ul,
li {
/* Remove all list styling. Set margin and padding to 0 avoid complex calculations */
list-style: none;
margin: 0;
padding: 0;
}

ul {
/* Fixed width divisible by 4 to get 4 equal columns */
width: 400px;
}

li {
/* box-sizing to include borders in width calculations, avoids complexity */
box-sizing: border-box;
/* Fixed width = 1/4 of ul width */
width: 100px;
/* Fixed height for each box. Should be 1/2 of X height. */
height: 100px;
/* Float each box */
float: left;
/* Center aligned text makes sample easier to view */
text-align: center;
/* Border to show edges of box */
border: 1px solid black;
}

li.spacer {
/* Fixed width = 1/2 of ul width */
width: 200px;
}

.X {
position: absolute;
/* Fixed left = li width (or 1/4 of ul width) */
left: 100px;
/* Fixed top = li height */
top: 100px;
/* Fixed width = li width x 2 (or 1/2 ul width) */
width: 200px;
/* Fixed height = li height x 2 */
height: 200px;
/* Background required to cover spacers underneath */
background: #ccc;
}

Note, an alternative for X that keeps some of the borders a little more consistent would be this:

.X {
position: absolute;
/* Fixed left = li width (or 1/4 of ul width) */
left: 101px;
/* Fixed top = li height */
top: 101px;
/* Fixed width = li width x 2 (or 1/2 ul width) */
width: 198px;
/* Fixed height = li height x 2 */
height: 198px;
/* Background required to cover spacers underneath */
background: #ccc;
}

Hope that helps. :)

Fotiman

3:58 pm on Dec 3, 2014 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Also, an alternative to using spacer items might be to apply a left margin to items 6 and 8.

li:nth-child(6),
li:nth-child(8) {
margin-left: 200px;
}

But you'd need to do some tweaking to get the borders right.

rainborick

4:00 pm on Dec 3, 2014 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



The 'float' property is meant to allow flexibility in web page layout. Absolute positioning gives you precision and predictability. For the layout you describe, even though you could do the job with floats, using absolute positioning is probably the better choice because the structure is very rigid. Just set the <ul> element's CSS 'position' to something like "position:relative; top:0; left:0;" to give the enclosed <li> elements a known point of reference.

asterickx

4:15 pm on Dec 3, 2014 (gmt 0)

10+ Year Member



Thank you guys!

@Fotiman:
Also, an alternative to using spacer items might be to apply a left margin to items 6 and 8.


Or I can just float:right items 6 and 8.
Anyway, I'd rather avoid using spacers, for they would be presentation-only (no actual content), and they are to be covered by the X box anyway.

But you'd need to do some tweaking to get the borders right.

In my project I don't need borders, so this wouldn't be a concern. But it's nice to know that I could have borders if needed.

@rainborick:
Just set the <ul> element's CSS 'position' to something like "position:relative; top:0; left:0;" to give the enclosed <li> elements a known point of reference.

I'm not sure I get it. It works (so far) without positioning the <ul> element. Do you have an example of a possible pitfall when not positioning the <ul>?

As to the X box, the absolute positioning stil stands as the best solution in this case. But just for the sake of it: could it be done with floats only?

--
Asterickx

Fotiman

7:16 pm on Dec 3, 2014 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month




But just for the sake of it: could it be done with floats only?

You mean floating the X box too, right? I think in order to do that, you would probably need to change the ordering of your content in a way that may not make sense. For example:

<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li><ul><li>5</li><li>7</li></ul></li>
<li class="X">X</li>
<li><ul><li>6</li><li>8</li></ul></li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
</ul>

And then the CSS:

ul,
li {
/* Remove all list styling. Set margin and padding to 0 avoid complex calculations */
list-style: none;
margin: 0;
padding: 0;
}

ul {
/* Fixed width divisible by 4 to get 4 equal columns */
width: 400px;
}

ul ul {
/* Nested ul is width of a single column */
width: 100px;
}

li {
/* box-sizing to include borders in width calculations, avoids complexity */
box-sizing: border-box;
/* Fixed width = 1/4 of ul width */
width: 100px;
/* Fixed height for each box. Should be 1/2 of X height. */
height: 100px;
/* Float each box */
float: left;
/* Center aligned text makes sample easier to view */
text-align: center;
/* Border to show edges of box */
border: 1px solid black;
}

li:nth-child(5),
li:nth-child(7) {
/* Fixed height = li height x 2 */
height: 200px;
}

li.X {
/* Fixed width = li width x 2 (or 1/2 ul width) */
width: 200px;
/* Fixed height = li height x 2 */
height: 200px;
/* Background required to cover spacers underneath */
background: #ccc;
}

But changing the order of the list items (and having a nested list) may not be what you want.

asterickx

11:59 pm on Dec 3, 2014 (gmt 0)

10+ Year Member



Thank you, Fotiman.

I suspected that it can be done by grouping two boxes into a taller one (nested lists), but I wasn't sure this was the only way. Thank you for the very detailed reply, Fotiman.

Actually I think it's enough to group items 5 and 7. Items 6 and 8 will float correctly without the need to be grouped together.

For my project, changing the order of the items wouldn't be a problem, but I would avoid nested lists since the nesting isn't required by the content structure (i.e. it would be strictly presentational).

I decided to go for the mixed solution: 12 floats + 1 absolute positioning. It's simple and makes sense, and it separates content from presentation.