CSS fluid columns, fixed margins; the holy grail of holy grails

后端 未结 10 618
深忆病人
深忆病人 2020-12-12 10:56

Update & Summary

I feel obligated to make this question clearer, now that there is a bounty attached.

(Also, I\'m pretty sure this will be child\'s

相关标签:
10条回答
  • 2020-12-12 11:16

    In referrence to the Original Question "Is there any way, using pure CSS, to achieve a fluid width columned layout with fixed width margins?"

    It is remarkable how extremely difficult CSS becomes with these kind of questions. The past week I've been working on a 'base template' to create my own 'holy grail', including border, margin and paddings... It seems CSS fails for these kind of questions. Though the question in mind is quite easy, it becomes (nearly?) impossible to achieve in CSS, especially cross-browser.

    The funny part is that these questions are easily resolved by using tables. I do not understand why we are being forced by the web-society to use div's instead for such vague arguments like 'semantics' and 'easy overview' as most arguments are weak or even false. People saying tables are giving more trouble, clearly have no understanding of the real difficulty that lies within CSS.

    Anyway, if you want to have an table-structure (as colums are part of a table) I suggest using 'display:table'.

    To achieve the image beneath the original question with pure CSS, the following could be used:

    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'd say it is quite overdone using additional divs for just a margin, but unfortunately CSS doesn't have a 'margin-box' model, which would actually solve a billion problems.

    This amount of nested code might make you think 'why not using other techniques?' as that may result in less code. For a very specific wish that would be the case. However, other techniques often involve floating or absolute positioning. These techniques can not achieve the same thing: floats for example can achieve colums that are equal in length, but when you want a border or margin you'll find yourself in trouble. For absolute positioning it 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 has failed to meet the requirements. While it is ment to replace tables for positiong, after all these years it is still not possible to get the same results. To achieve 'the holy grail of holy grails' table structures are not just the easiest way, there are also the only way... at least, for as far I know after trying hundreds of possibilities.

    The remaining question is: why using divs if you're using them as tables? This I do not fully understand myself, but people seem to have their reasons for that.

    0 讨论(0)
  • 2020-12-12 11:18

    I use the grid of OOCSS for this

    https://github.com/stubbornella/oocss

    I recently put a demo online on my own site since there are no proper examples online :(

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

    0 讨论(0)
  • 2020-12-12 11:25

    I have recently developed an alternative solution for this which allows for any combination of flexible columns within a row with a fixed and consistent margin across all columns, regardless of the parent element's width.

    This doesn't use any JavaScript and works in IE8+.

    In this solution the margin is defined on two classes - so it is easy to change it for responsive designs. The column widths are also representative of the space they use, for example a 2 column row has widths of 50% and a 4 column row has widths of 25%.

    You can see an example at http://www.andrewjamestait.co.uk/conflexgrids/

    Or it is available on GitHub at https://github.com/andrewjtait/conflexgrids

    0 讨论(0)
  • 2020-12-12 11:26

    Try this pure CSS2 solution: demo fiddle

    Base CSS (fiddle without the cosmetics):

    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 this to work with an arbitrary number of columns, you have to add an extra class to the container specifying the column count:

    <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 fiddle demonstrating a number of various column counts.

    Possible bug:

    Theoretically, imho this solution should work for any number of columns for every possible minimum column width in any browser window width. But it seems, all browsers prove not being able to handle: 1. a large number of 1 column width columns, or 2. a small browser window width.

    Note that all browsers with a minimum width of 1440 pixels, which equals 12 times 120 pixels (the space occupied by all 10px margins), handle the solution just fine. And when you use 2 or more column width colums, the requirement for the minimum browser width indeed drops to 720 pixels (6 * 120px). This last case sounds more realistic to be, but still, I cannot explain this browser behaviour.

    I tried fixing the issue by introducing an additional last column class as demonstrated by this fiddle, but it does not solve the problem for small browser widths. It dóes solve a tiny rounding error due to the broken width percentages though, but that issue could be ignored I suppose.

    I would like to hear from other css experts on this one, so I added a bounty.

    0 讨论(0)
  • 2020-12-12 11:26

    An easier way to get the same effect is to let the content inside your columns create your gutters rather than applying margins/padding to the columns themselves. This can be done with 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;
    }
    

    This also simplifies sizing your columns, nesting, and applying backgrounds to your lego pieces.

    0 讨论(0)
  • 2020-12-12 11:33

    Check out thirtydot's answer in this thread for a pure CSS/HTML (Fluid layout with equally spaced "columns" without JavaScript)...

    Fluid width with equally spaced DIVs

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

    Modification of the JSFiddle demonstrates that the "columns" can be made to be different fixed widths and still have equal and fluid margins.

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

    Then finally, another example using percentages while still maintaining equal and fluid margins.

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

    I realize this may not be an exact solution but it gets you pretty close, I think.

    0 讨论(0)
提交回复
热议问题