CSS fluid columns, fixed fields holy grail of holy grails

Update and Summary

I feel obligated to make this question clearer now that there is generosity.

(Also, I’m sure it will be a child’s game when the CSS3 calc() unit value is supported, something like width: calc(25% - 5px) , although we will probably look at our minds on the Internet for this moment)

I am working on a CSS framework for several projects that share design requirements; namely, the liquid layout of 12 columns. Using floating .column elements with a percentage width of (100% / 12) x col_size is quite simple. However, the problem is with the addition of fixed fields (or any form of spacing) between the columns.

My initial attempt was to use the current columns as described, with a .panel child nested in each. The following is a snippet of HTML / CSS (short for brevity):

 .column{ float: left; display: inline-block; } .width-01{ width: 8.3333%; } .width-02{ width: 16.6666%; } .width-03{ width: 25%; } /* etc */ .panel{ width: 100%; padding: 5px; box-sizing: border-box; /* so padding doesn't increase width */ } 
 <div class="column width-02"> <div class="panel">Width-02</div> </div> <div class="column width-03"> <div class="panel">Width-03</div> </div> <div class="column width-02"> <div class="panel">Width-02</div> </div> <div class="column width-05"> <div class="panel">Width-05</div> </div> 

This snippet will create a layout similar to the image below, however all .panel elements are indented 5px on all sides. I'm trying to make the edge of the contents of the outer columns flush with the edge of the view port (or the parent container, for that matter) . Another approach would be to exclude the .panel class and just go with the columns:

 .column{ float: left; display: inline-block; padding-left: 10px; box-sizing: border-box; } .column:first-child{ padding-left: 0px; } .width-01{ width: 8.3333%; } .width-02{ width: 16.6666%; } .width-03{ width: 25%; } /* etc */ 
 <div class="column width-02">Width-02</div> <div class="column width-03">Width-03</div> <div class="column width-02">Width-02</div> <div class="column width-05">Width-05</div> 

Again, this works well, bringing the results even closer to the image results below, but now the (actual) problem is that the gasket eats across the width of the columns screwing up the width distribution. The :first-child column has 10 pixels (or regardless of the size of the field) a larger width of the content area than its siblings.

It may seem harmless, even imperceptible; however, there are several examples where the exact (as possible) distribution of the width between the elements is either necessary or will facilitate the situation.

So whether padding, margin or any combination of them is used; Is there any solution for fluid columns, fixed fields, with a uniform distribution of the gutter space, which will not enclose the marginal content area (*** haha ​​* ) from neighboring columns? **




Original question

Due to the simple lack of results in my searches and attempts, I came to the conclusion that this is impossible. If in any case an answer can be given, I am sure that he is here.

Is there a way using pure CSS to achieve column width with column width with fixed width fields?

Important Note . This figure is just an example, not the specific layout that I want to achieve. This solution should allow for any combination of adjacent columns with a total width distribution of 12 or less. View the popular 960 grid for reference.)

super_awesome_layout.css
Note In a 12-column layout, the distribution of the column widths in the image is 2, 3, 2, and 5, respectively.

So far, I have resorted to a grid that, using interest, has almost achieved this. The problem is that in order to reach the fields, each column requires an extra child (I call them .panel ):

 width: 100%; box-sizing: border-box; padding: 10px; 

This is again almost normal; the problem is that the first and last column have external “fields” ( 10px ), and the “fields” between each column are doubled ( 2 x 10px )

Of course, with the inclusion of a new type of CSS3 calc() value, this could be solved much easier. Something in the direction of:

 .width-12 > .panel{ width: 100%; } .width-09 > .panel{ width: calc(75% - 10px); margin: ...; } 

I have some Javascript fixes, I hacked some things that "work", but I'm in the quest. Hopefully the most sacred of the grails exists.

The following solution, and one @avall provided (although certainly a good choice to simplify), unfortunately, is not what I am looking for. The main problem is that the fields are not evenly distributed between the columns.

The only way I can see this work is to reduce the .panel indent to 5px and something like:

 .column:first-child > .panel { padding-left: 0px; } .column:last-child > .panel { padding-right: 0px; } /* not necessary? in any case, haven't tested */ .column:only-child > .panel { padding-right: 0px; padding-left: 0px; } 

This solution is unacceptable only because IE8 cannot recognize the :last-child pseudo :last-child (in this case :only-child ).

+48
html css fluid-layout
Aug 25 2018-11-12T00:
source share
10 answers

I finally understood. For hundreds of hours wasted over the last decade (although I rely on some css that would not work a year ago anyway). I solved this without any errors. and in IE8 +.

Please prepare 2001: A Space Odyssey Music because I am landing this boat.

The genius and trick of this method is to use elements of the built-in block, and then use the word-spacing to balance using the negative right edge. The negative right margin on it will stretch the elements together, allowing you to set 100% width and still fit together, but leave the elements overlapping. Setting a negative margin for the parent simply overrides the child margin with respect to the effect of interacting with the total width (the “100% width” magic we are trying to hit "). Filling serves only to increase the size of the element and it is useless with respect to the counteracting margin. It often used with a box in jury decisions fraught with this problem, due to the loss of the ability to indent all others (and margins) and probably requires more wrapping.

word-spacing provides a magical “third way” for adding or removing the horizontal distance between two elements if they are an inline block, since in this case they will be considered as one “word” and any spaces between them will be collapsed to one single controlled property " word-spacing ". Other than this trick, I don’t know any other way to get this 100% result.

I humbly submit the final answer to the problem with flexible columns with fixed grooves. I call my decision the omega maneuver. It has the ability to process arbitrary columns of mixed width (accurate to 100% of the total width or slightly smaller for rounding), any size of the gutter, any predetermined number of columns in width, processes an arbitrary number of rows with automatic packaging and uses elements of the built-in block, therefore provides parameters vertical alignment that come with the built-in block, and it does not require additional markup and requires only one class declaration in the container (not counting boiling column width). I think the code speaks for itself. Here's the code implementation for 2-6 columns using 10px gutters and bonus helper classes for percentages.

EDIT: An interesting puzzle. I managed to get two slightly different versions; one for mozilla and ie8 +, the other for webkit. It seems the word-spacing trick doesn't work in webkit, and I don't know why another version works in webkit, but not ie8 + / mozilla. The combination of both allows you to cover everything, and I am ready to bet on a way to unify this tactic or something very similar to the solution to this problem.

EDIT2: Mostly got it! The magical text-align: justify gets WebKit almost there with word spacing. The spacing just seems a little tiny, like the pixels on the right and maybe one extra in the gutters. But it is useful and seems more robust in maintaining columns than anything I've used before. It never drops to fewer columns; it will shrink until the browser gets a horizontal scrollbar.

Edit3: He has a little close to perfection. Setting the font size to 0 normalizes most of the remaining problems with disabling the interval. You just need to fix IE9, which destroys it if the font is 0.

EDIT4: Got a response to IE from some other fluid width messages: -ms-text-justify: distribute-all-lines . Tested in IE8-10.

 /* The Omega Maneuver */ [class*=cols] { text-align: justify; padding-left: 10px; font-size: 0; -ms-text-justify: distribute-all-lines; } [class*=cols]>* { display: inline-block; text-align: left; font-size: 13px; word-spacing: normal; vertical-align: top; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } .cols2 { word-spacing: 20px; padding-right: 20px; } .cols3 { word-spacing: 30px; padding-right: 30px; } .cols4 { word-spacing: 40px; padding-right: 40px; } .cols5 { word-spacing: 50px; padding-right: 50px; } .cols6 { word-spacing: 60px; padding-right: 60px; } .cols2 > * { margin-right: -10px; } .cols3 > * { margin-right: -20px; } .cols4 > * { margin-right: -30px; } .cols5 > * { margin-right: -40px; } .cols6 > * { margin-right: -50px; } 

Some helpers:

 .⅛, .⅛s >* { width: 12.50%; } .⅙, .⅙s >* { width: 16.66%; } .⅕, .⅕s >* { width: 20.00%; } .¼, .¼s >* { width: 25.00%; } .⅓, .⅓s >* { width: 33.00%; } .⅜, .⅜s >* { width: 37.50%; } .⅖, .⅖s >* { width: 40.00%; } .½, .½s >* { width: 50.00%; } .⅗, .⅗s >* { width: 60.00%; } .⅝, .⅝s >* { width: 62.50%; } .⅔, .⅔s >* { width: 66.00%; } .¾, .¾s >* { width: 75.00%; } .⅘, .⅘s >* { width: 80.00%; } .⅚, .⅚s >* { width: 83.33%; } .⅞, .⅞s >* { width: 87.50%; } .blarg-five-twelfs { width: 41.66%; } 

You can see my opus magnum in action amongst the glory field here: http://jsfiddle.net/xg7nB/15/

 <div class="cols4"> <div class="⅙">This is my magnum opus</div> <div class="¼">I finally beat css</div> <div class="⅙">⚉ ☺ ☻ ♾ ☢</div> <div class="blarg-five-twelfs">I BEAT IT FOREVER</div> </div> 

The absolute minimum implementation, using as an example 4 equal widths (25%) of column widths and 10px gutters, is as follows:

 .fourEqualCols { word-spacing: 40px; padding: 0 40px 0 10px; text-align: justify; font-size: 0; -ms-text-justify: distribute-all-lines; } .fourEqualCols>* { margin-right: -30px; width: 25%; display: inline-block; word-spacing: normal; text-align: left; font-size: 13px; } <div class="fourEqualCols "> <div>GLORIOUSLY CLEAN MARKUP</div> <div>I hate extra markup and excessive class props</div> <div>Naked code</div> <div>get intimate</div> </div> 

Soooo this code essentially replaces almost any existing grid structure? If you can arbitrarily install gutters, then just create sets of columns that are 100% wide, which is strictly superior to most / all meshes in fact, right? If you are not developing for IE7 anymore, like many of us, then in combination with the window size: border-box displays indents and borders also without problems.

Edit: oh, you wanted you to be on par with the sides of the container. There is no problem with this, I had to specifically add side gutters so that we can just change some values ​​to 10 and get rid of the gasket and voila. http://jsfiddle.net/bTty3/

 [class^=cols] { text-align: justify; font-size: 0; -ms-text-justify: distribute-all-lines; } [class^=cols] >* { display: inline-block; text-align: left; font-size: 13px; word-spacing: normal; vertical-align: top; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } .cols2 { word-spacing: 20px; padding-right: 10px; } .cols3 { word-spacing: 30px; padding-right: 20px; } .cols4 { word-spacing: 40px; padding-right: 30px; } .cols5 { word-spacing: 50px; padding-right: 40px; } .cols6 { word-spacing: 60px; padding-right: 50px; } .cols2 >* { margin-right: 0 } .cols2 >* { margin-right: -10px; } .cols3 >* { margin-right: -20px; } .cols4 >* { margin-right: -30px; } .cols5 >* { margin-right: -40px; } .cols6 >* { margin-right: -50px; } 

Same html

 <div class="cols4"> <div class="⅙">This is my magnum opus</div> <div class="¼">I finally beat css</div> <div class="⅙">⚉ ☺ ☻ ♾ ☢</div> <div class="blarg-five-twelfs">I BEAT IT FOREVER</div> </div> 

I beat CSS here's your proof

+64
Aug 31 '11 at 11:29
source share
Studvork - online student assistance service

Try this pure CSS2 solution: demo script

CSS basis ( fiddle without makeup):

 html, body { padding: 0; margin: 0; } #wrap { padding-right: 30px; overflow: hidden; } .col { float: left; margin-left: 40px; margin-right: -30px; } .col:first-child { margin-left: 0; } .small { width: 16.66%; } .medium { width: 25%; } .large { width: 41.66%; } 

HTML:

 <div id="wrap"> <div class="col small"></div> <div class="col medium"></div> <div class="col small"></div> <div class="col large"></div> </div> 

Tested on Win7 in IE7, IE8, IE9, Opera 11.50, Safari 5.0.5, FF 6.0, Chrome 13.0.




Update:

Now, if you like working with an arbitrary number of columns, you need to add an additional class to the container, indicating the number of columns:

 <div class="cols-12 count-04"> <div class="col width-02"></div> <div class="col width-03"></div> <div class="col width-02"></div> <div class="col width-05"></div> </div> 

See this updated script for a few different columns.

Possible error:

Theoretically, this solution should work for any number of columns for each possible minimum column width in any browser window width. But it seems that all browsers cannot handle: 1. a large number of columns of column width or 2. a small width of the browser window.

Please note that all browsers with a minimum width of 1440 pixels, which is 12 times 120 pixels (the space occupied by all fields of 10 pixels), do an excellent job with the solution. And when you use 2 or more columns of column width, the minimum browser width requirement really drops to 720 pixels (6 * 120 pixels). This last case sounds more realistic, but, nevertheless, I can not explain this behavior of the browser.

I tried to fix the problem by introducing an additional last column class, as shown by this script , but this does not solve the problem for small browser widths. This resolves a tiny rounding error due to a gap in width, though, but this question can be ignored, I suppose.

I would love to hear from other css experts about this, so I added generosity.

+8
Aug 26 '11 at 5:26 a.m.
source share

Why don't you use

 .column > .panel { padding: 10px 0 10px 10px; } .column:first-child > .panel { padding-left: 0px; } 

It will make 10px spaces only between drawers and without using the last-child.

+7
Aug 25 2018-11-11T00:
source share

Check out thirty answers in this thread for pure CSS / HTML (Fluid layout with equally spaced "columns" without JavaScript) ...

Fluid Width with Equidistant DIVs

http://jsfiddle.net/thirtydot/EDp8R/

The JSFiddle modification demonstrates that "columns" can be different fixed widths and still have equal and current fields.

http://jsfiddle.net/EDp8R/43/

Then, finally, another example that uses percentages, while maintaining equal and current fields.

http://jsfiddle.net/EDp8R/45/

I understand that this may not be the exact solution, but it seems to be getting pretty close.

+2
Aug 31 '11 at 15:43
source share

In the links to the original question "Is there a way, using pure CSS, to achieve column width with stream width with fixed width boundaries?"

It’s great how extremely complex CSS gets with such questions. Last week, I worked on a basic template for creating my own holy grail, including borders, margins, and shims ... CSS doesn't seem to be suitable for such issues. Although the question in mind is pretty simple, it becomes (almost?) Impossible in CSS, especially in a cross browser.

The funny thing is that these issues are easily resolved using tables. I don’t understand why we are forced by the web community to use div instead of such vague arguments as “semantics” and “simple overview”, since most arguments are weak or even false. The people who speak the tables bring more problems, clearly not understanding the real difficulty that lies in CSS.

In any case, if you want to have a table structure (since the columns are part of the table), I suggest using "display: table".

To achieve the image under the original question using pure CSS, you can use the following:

CSS

 html,body{ margin: 0px; padding: 0px; height: 100%; width: 100%; overflow: auto; } .table{ background: pink; display: table; width: 100%; height: 100%; } .tableRow{ display: table-row; } .tableCell{ display: table-cell; vertical-align: top; height: 100%; } /* Ensures the full size of the table-cell has the behaviour of a block-element. This is needed, because 'table-cell' will behave differently in different browsers. */ .tableCell>div{ height: 100%; } /* Padding has to be used instead of margin in 'border-box' modus. */ .tableCell>div>div{ height: 100%; box-sizing:border-box; -moz-box-sizing:border-box; } /* The final content. */ .tableCell>div>div>div{ background: lightblue; padding: 5px; height: 100%; box-sizing:border-box; -moz-box-sizing:border-box; } #col1{ width: 16.66%; } #col1>div>div{ padding-right: 10px; } #col2{ width: 25%; } #col2>div>div{ padding-right: 10px; } #col3{ width: 16.66%; } #col3>div>div{ padding-right: 10px; } #col4{ width: 41.66%; } 

HTML

 <div class="table"> <div class="tableRow"> <div id='col1' class="tableCell"> <div><div><div>16.66%</div></div></div> </div> <div id='col2' class="tableCell"> <div><div><div>25%</div></div></div> </div> <div id='col3' class="tableCell"> <div><div><div>16.66%</div></div></div> </div> <div id='col4' class="tableCell"> <div><div><div>41.66%</div></div></div> </div> </div> </div> 

I would say that he was overdoing it using extra divs for just margin, but unfortunately CSS does not have a “margin-box” model that would actually solve a billion problems.

This amount of nested code might make you think, “why not use other methods?” as this can lead to a reduction in the amount of code. For a very specific desire, that would be so. However, other methods often include smooth or absolute positioning. These methods cannot achieve the same thing: floats, for example, can reach the same colonies in volume, but when you want to get a border or margin, you will be in trouble. For absolute positioning, this is more like the opposite: you can solve the margin problem, but the height can only be based on one column.

In my opinion, CSS did not meet the requirements. Despite replacing the tables for position g, after all these years it is still impossible to get the same results. To reach the Holy Grail of the Holy Grails, table structures are not just the easiest way, there is also the only way ... at least as far as I know, when I tried a hundred possibilities.

The question remains: why use divs if you use them as tables? I don’t fully understand myself, but people seem to have reasons for this.

+2
May 03 '12 at 1:55 pm
source share

I use the OOCSS grid for this

https://github.com/stubbornella/oocss

I recently posted a demo online on my own site, as there are no suitable examples online :(

http://www.leipeshit.com/awesome_stuff/oocss/core/grid/grids_all.html

+1
01 Sep '11 at 4:14
source share

An easier way to get the same effect is to allow the content inside your columns to create your gutters, rather than applying margins / indents to the columns themselves. This can be done using fixed, fluid, elastic, etc. Grids.

For example:

 /* Gutters */ h1, h2, h3, h4, h5, h6, p, ul, ol, blockquote, hr, address, pre, object, fieldset { margin-right: .75rem; margin-left: .75rem; padding-right: .75rem; padding-left: .75rem; } 

It also makes it easy to calibrate your columns, nesting and applying backgrounds to your lego parts.

+1
Feb 01 2018-12-12T00:
source share

, , : border-box ?

0
11 . '13 9:12
source share
0
06 . '15 11:18
source share

div , . , .

: pureCSS pure-g - , pure-u- * - node (display: inline-block), div. - pureCSS, .

 .pure-g.spacing { margin: 0 -10px; } .pure-g.spacing [class *= "pure-u"] > div { margin: 10px; } 

. , - .

,

0
15 . '15 15:14
source share



All Articles