48 votes

Colonnes fluides CSS, marges fixes; le saint graal de saint graal

Mise À Jour Et Résumé

Je me sens obligé de faire de cette question plus clair, maintenant qu'il y a un bounty ci-joint.

(Aussi, je suis sûr que ce sera un jeu d'enfant lorsque l' calc() CSS3 unité de valeur est prise en charge, de faire quelque chose comme width: calc(25% - 5px); cependant, nous allons probablement être la navigation sur internet dans nos esprits par ce point)

Je travaille sur un framework CSS pour les quelques projets qui partagent des exigences de conception, à savoir un liquide de 12 colonnes de mise en page. À l'aide flottait .column éléments avec un pourcentage de la largeur de (100% / 12) x col_size, c'est assez facile. Toutefois, la question qui vient avec l'ajout de marges fixes (ou de toute forme de l'espacemententre les colonnes.

Ma première tentative a utilisé le fluide colonnes comme décrit, avec un .panel enfant imbriquée dans chaque. HTML/CSS extrait qui suit (réduite pour des raisons de concision):

.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>

Cet extrait serait de produire une mise en page similaire à celle de l'image ci-dessous, cependant, tous .panel éléments 5px rembourrage sur tous les côtés. J'essaie de rendre le contenu de bord de l'extérieur des colonnes de niveau avec le bord de la vue-port (conteneur parent ou d'ailleurs). Une autre approche serait d'éliminer l' .panel classe tout à fait, et juste aller avec des colonnes:

.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>

Encore une fois, cela fonctionne bien, produire des résultats encore plus proche de celle de l'image ci-dessous, mais maintenant la (réelle) problème est que le rembourrage est en train de manger dans la largeur des colonnes vissage jusqu'à la largeur de la distribution. L' :first-child colonne a 10 pixels (ou quelle que soit la taille de la marge est) une plus grande largeur de la zone de contenu que les frères et sœurs.

Cela peut sembler anodin, même imperceptible; cependant, il existe quelques cas où le fait d'avoir exacts (aussi précis que possible) de la largeur de la distribution entre les éléments est nécessaire, ou rendrait les choses carrément plus facile.

Et donc, si l'utilisation de rembourrage, de la marge, ou une combinaison de ceux-ci; est-il une solution pour le fluide colonnes, marges fixes, avec une distribution uniforme de l'espace de gouttière qui ne sont pas rob "marginale" (haha) de la zone de contenu de la colonne voisine?


Question D'Origine

En raison de la simple absence de résultats dans mes recherches et tentatives, j'en ai conclu que c'est impossible. Si n'importe où peut donner une réponse, cependant, je suis certain qu'il est ici.

Est-il possible, à l'aide de pure CSS, afin d'obtenir un liquide largeur de colonnes de mise en page à largeur fixe les marges?

Remarque importante: Cette figure n'est qu'un exemple, et non pas la mise en page spécifique, je suis à la recherche à réaliser. Une solution devrait permettre à n'importe quelle combinaison de colonnes adjacentes, la largeur totale de la distribution totalisant 12 ou moins. Envisager le populaire 960 de la grille de référence.)

super_awesome_layout.css
Remarque: Dans un 12 mise en page en colonnes, la largeur de la distribution de l'image en colonnes 2, 3, 2, et 5, respectivement.

Jusqu'à présent, j'ai eu recours à une grille qui, à l'aide de pourcentages, près de l'accomplit. Le problème est, dans l'ordre pour atteindre les marges, chaque colonne requiert un autre enfant (je les appelle, .panel) avec:

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

C'est, encore une fois près, très bien; le problème avec cette approche est que la première et la dernière colonne externe de la marge (10px) et les "marges" entre chaque colonne sont doublés (2 x 10px)

Certes, avec l'inclusion de la nouvelle CSS3 calc() type valeur, cela pourrait être résolu beaucoup plus facilement. Quelque chose dans le sens de:

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

J'ai un peu de Javascript de bugs, j'ai piraté quelques trucs qui "fonctionne", mais je suis sur une quête. Espérons-le, le lieu le plus sacré du graal existe.

La solution suivante, et l'un @avall (bien qu'certainement un bon choix sur la simplification) ne sont malheureusement pas ce que je cherche. Le principal problème étant, les marges ne sont pas répartis uniformément entre les colonnes.

La seule façon que je peux voir ce travail est la réduction de l' .panel rembourrage 5px et quelque chose comme:

.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;
}

Cette solution n'est pas acceptable, seulement parce que IE8 ne parvient pas à reconnaître l' :last-child (et en :only-child) pseudo-sélecteurs.

64voto

benvie Points 6181

J'ai finalement compris. Après les centaines d'heures perdues sur et en dehors au cours de la dernière décennie (même si je suis plutôt un peu de css qui n'aurait pas travaillé l'année il y a de toute façon). Je l'ai résolu sans pièges. et IE8+.

Veuillez préparer le 2001: l'Odyssée de l'Espace de la Musique parce que je suis d'atterrissage de ce bateau.

Le génie et le truc de cette méthode est à utiliser inline-block éléments, puis l'utilisation de word-spacing pour contrebalancer l'aide d'un négatif de la marge de droite. Un droit négatif de la marge sur ses propres va tirer les éléments ensemble, vous permettant d'avoir 100% de largeur et encore en forme des choses entre les deux, mais laissez les éléments qui se chevauchent. Réglage de la marge négative sur le parent annule l'enfant de la marge en ce qui concerne l'effet sur l'interaction avec largeur totale (la magie du "100% de la largeur de la" marque nous essayons de frapper"). Rembourrage ne sert qu'à augmenter la taille de l'élément de sa sur et est inutile en ce qui concerne les contre-statuant à la marge. Il est souvent utilisé avec box-sizing dans le jury truqué des solutions à ce problème, au détriment de la perte de la capacité à utiliser de rembourrage à tous les autres (et de la marge) et probablement exiger plus wrapper éléments.

word-spacing fournit le magique "troisième voie" pour ajouter ou supprimer distance horizontale entre deux éléments, à condition qu'ils soient inline-block, car ils seront comptés comme un seul "mot" dans ce cas, et tous les espaces entre collpapse vers le bas à un seul contrôlable "word-spacing" de la propriété. À côté de ce truc, je ne suis pas au courant d'un autre moyen d'obtenir ce résultat à 100%.

Je humblement présente l'ultime réponse à l'fixe les gouttières flex-colonnes problème. Je, soussigné, nom de ma solution "l'oméga de manœuvre". Il est livré avec la capacité de gérer arbitraire mixte largeur des colonnes (ajouter jusqu'à 100% de la largeur totale exactement ou un peu moins pour l'arrondissement), tout gouttière taille, tout montant prédéfini de colonnes en largeur, poignées arbitraire, les montants de lignes de l'auto-enveloppant, et utilise inline-block éléments si, par conséquent, fournit la verticale à l'alignement des options qui viennent avec inline-block, ET il ne nécessite pas d'extra balisage et ne nécessite qu'une seule déclaration de classe sur le récipient (pas de comptage de définir les largeurs de colonne). Je pense que le code parle de lui-même. Voici le code de mise en œuvre pour 2 à 6 colonnes à l'aide de 10px les gouttières et les bonus des classes d'assistance pour les pourcentages.

EDIT: intéressant énigme. J'ai réussi à obtenir deux versions légèrement différentes; l'une pour mozilla et ie8+, l'autre pour webkit. Il semble que le mot de l'espacement de truc qui ne fonctionne pas dans webkit, et je ne sais pas pourquoi l'autre version fonctionne dans webkit, mais pas ie8+/mozilla. En combinant les deux, vous reçoit de couverture au-dessus de tout et je suis prêt à parier qu'il y un moyen d'unifier cette tactique ou quelque chose de très similaire à contourner le problème.

EDIT2: pour la Plupart de se! Magiques text-align: justify obtient WebKit y est presque avec le mot-espacement. L'espacement semble juste un tout petit peu, comme une question de pixels sur la droite et peut-être un extra dans les caniveaux. Mais c'est utilisable et il semble plus fiable sur le fait de garder les colonnes que tout ce que j'ai utilisé avant. Il n'a jamais côtelettes à moins de colonnes, il va compresser jusqu'à ce que le navigateur reçoit une barre de défilement horizontale.

Edit3: j'Ai un peu proche de la perfection. Réglage de la taille de police 0 normalise la plupart des autres questions dont l'espacement est éteint. Dois corriger IE9 maintenant qui s'effondre si c'est la police de la taille de 0.

EDIT4: j'Ai la réponse à la d'IE à partir d'un autre fluide largeur de messages: -ms-text-justify: distribute-all-lines. Testé avec 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; }

Certaines aides:

.⅛, .⅛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%; }

Vous pouvez témoigner de mon magnum opus en action parmi un champ de gloire ici: 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>

Le minimum de mise en œuvre, à l'aide d'un exemple 4 de largeur égale (25%) de la largeur de cols et de 10px gouttières est comme suit:

.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 ce code remplace essentiellement à peu près tout le réseau existant cadre de droite? Si vous pouvez fixer arbitrairement les gouttières et puis il suffit de faire des séries de colonnes qui atteint 100% de largeur, c'est strictement supérieur à la plupart/tous les grille des cadres, en fait, n'est-ce pas? Si vous n'êtes pas en développement pour IE7 plus comme beaucoup d'entre nous alors que combiné avec box-sizing: border-box rend padding et border également un non-problème.

Edit: ah oui tu voulais être de niveau avec les côtés du conteneur. Aucun problème avec cela, j'ai dû ajouter du côté des gouttières nous pouvons donc il suffit de changer quelques valeurs de 10 et de se débarrasser de la mousse et de l'alto. 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; }

Même 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

8voto

NGLN Points 25671

Essayez cette pure CSS2 solution: démo de violon

La Base de CSS (violon sans les cosmétiques):

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>

Testé sur Win7 dans IE7, IE8, IE9, Opera 11.50, Safari 5.0.5, FF 6.0, Chrome 13.0.


Mise à jour:

Maintenant, si vous voulez que cela fonctionne avec un nombre quelconque de colonnes, vous devez ajouter une classe supplémentaire pour le conteneur de spécifier le nombre de colonnes:

<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>

Voir cette mise à jour de violon en démontrant un certain nombre de différents colonne de compte.

Bug Possible:

Théoriquement, à mon humble avis, cette solution devrait fonctionner pour n'importe quel nombre de colonnes pour chaque minimum possible de la largeur de colonne dans n'importe quel navigateur largeur de la fenêtre. Mais il semble, tous les navigateurs s'avère ne pas être en mesure de gérer: 1. un grand nombre de 1 colonne largeur des colonnes, ou 2. une petite largeur de la fenêtre du navigateur.

Notez que tous les navigateurs avec une largeur minimale de 1440 pixels, ce qui est égal à 12 fois 120 pixels (l'espace occupé par l'ensemble des 10px marges), la poignée de la solution de l'amende juste. Et quand vous utilisez 2 ou plus de largeur de colonne en colonnes, l'exigence minimale de la largeur du navigateur en effet gouttes de 720 pixels (6 * 120px). Ce dernier cas semble le plus réaliste, mais encore, je ne peux pas expliquer ce comportement du navigateur.

J'ai essayé de résoudre le problème par l'introduction d'un supplément de dernière colonne de la classe comme l'a démontré par ce violon, mais elle ne résout pas le problème pour les petites navigateur largeurs. Il dóes résoudre une petite erreur d'arrondi en raison de la brisure de la largeur des pourcentages, mais cette question pourrait peut-être ignoré, je suppose.

J'aimerais entendre d'autres css experts sur celui-ci, j'ai donc ajouté une prime.

7voto

avall Points 1701

Pourquoi n'utilisez-vous pas

 .column > .panel {
    padding: 10px 0 10px 10px;
}

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

Cela créera des espaces de 10 pixels uniquement entre les boîtes et sans utiliser last-child.

2voto

Sparky Points 36014

Découvrez thirtydot de réponse dans ce fil de discussion pour un pur CSS/HTML (mise en page Fluide avec équidistants "colonnes" sans JavaScript)...

Liquide de largeur espacés de façon égale, les DIVs

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

Modification de la JSFiddle démontre que les "colonnes" peut être fait pour être différent des largeurs fixes et toujours égal et fluide marges.

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

Puis enfin, un autre exemple à l'aide de pourcentages, tout en conservant l'égalité et de liquide de marges.

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

Je réalise que j'ai peut-être pas de solution exacte, mais il est assez proche, je pense.

2voto

Kevin Driessen Points 101

Dans referrence à la Question initiale "Est-il possible, à l'aide de pure CSS, afin d'obtenir un liquide largeur de colonnes de mise en page à largeur fixe les marges?"

Il est remarquable de voir comment extrêmement difficile CSS devient, avec ce genre de questions. La semaine dernière j'ai travaillé sur un "modèle de base" pour créer mon propre "saint-graal", y compris la frontière, de marge et de rembourrages... Il semble CSS échoue pour ce genre de questions. Bien que la question à l'esprit est assez facile, il devient (presque?) impossible à réaliser dans la CSS, en particulier croix-navigateur.

Le plus drôle, c'est que ces questions sont facilement résolus en utilisant des tables. Je ne comprends pas pourquoi nous sommes contraints par le web de la société à utiliser des div à la place pour une telle vague des arguments comme "sémantique" et "vue d'ensemble facile" comme la plupart des arguments sont faibles ou même faux. Les gens en disant tables donnant plus de difficulté, n'ont manifestement rien à la compréhension de la véritable difficulté réside dans le CSS.

De toute façon, si vous voulez avoir une table-structure (colonnes sont une partie d'un tableau) je suggère l'utilisation de 'display:table'.

Pour obtenir l'image en dessous de la question d'origine avec pur CSS, les éléments suivants pourraient être utilisés:

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>

Je dirais que c'est assez surfait à l'aide d'autres divs pour juste une marge, mais malheureusement, le CSS n'a pas une marge boîte " modèle, qui seraient en fait de résoudre un milliard de problèmes.

Cette quantité de code imbriqué pourrait vous faire penser " pourquoi pas à l'aide d'autres techniques?' comme cela peut résultat en moins de code. Pour certaines souhaitent que ce serait le cas. Cependant, d'autres techniques impliquent souvent flottante ou d'un positionnement absolu. Ces techniques ne peuvent pas faire la même chose: flotteurs, par exemple, peut atteindre des colonnes qui sont de longueur égale, mais quand vous voulez une bordure ou de marge, vous allez vous retrouver en difficulté. Pour le positionnement absolu, il est plus comme le contraire: vous pouvez résoudre la marge de problème, mais la hauteur ne peut être fondée que sur une seule colonne.

À mon avis, le CSS n'a pas satisfait aux exigences. Alors qu'il est ment pour remplacer les tables pour positiong, après toutes ces années, il n'est toujours pas possible d'obtenir les mêmes résultats. Pour atteindre 'le saint graal de saint graal' des structures de table ne sont pas seulement le moyen le plus facile, il y a aussi le seul moyen... au moins, pour autant que je sais après avoir essayé des centaines de possibilités.

La question qui reste est: pourquoi utiliser des divs si vous les utilisez que des tables? Ce que je n'ai pas de comprendre pleinement moi-même, mais les gens semblent avoir leurs raisons pour cela.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X