Empêcher les div flottants de s'enrouler

84

Je veux avoir une rangée de divs (cellules) qui ne s'enroulent pas si le navigateur est trop étroit pour les adapter.

J'ai cherché dans Stack et je n'ai pas trouvé de réponse fonctionnelle à ce que je pense devrait être une simple question CSS.

Les cellules ont une largeur spécifiée. Cependant, je ne veux pas spécifier la largeur de la ligne, la largeur doit être automatiquement la largeur de ses cellules enfants.

Si la fenêtre est trop étroite pour accueillir les lignes, le div doit déborder de barres de défilement.

Veuillez fournir votre réponse sous forme d'extrait de code fonctionnel, car j'ai essayé beaucoup de solutions que j'ai vues ailleurs (comme spécifier la largeur: 100% et elles ne semblent pas fonctionner).

Je recherche une solution uniquement HTML / CSS, pas de JavaScript.

.row {
  float: left;
  border: 1px solid yellow;
  width: 100%;
  overflow: auto;
}
.cell {
  float: left;
  border: 1px solid red;
  width: 200px;
  height: 100px;
}
<div class="row">
  <div class="cell">a</div>
  <div class="cell">b</div>
  <div class="cell">c</div>
</div>

Pour le moment, je codifie en dur la largeur de la ligne en un très grand nombre.

Nicolas
la source
1
l'une des réponses ci-dessous a-t-elle fonctionné pour vous? Je n'ai aucun succès avec aucun d'entre eux.
John Fitzpatrick
J'ai juste essayé toutes les réponses, et aucune n'a fonctionné pour moi. Le problème était que je devais centrer deux divs flottants à gauche et empêcher celui de droite d'être poussé en dessous vers la gauche après le redimensionnement de la fenêtre.
Bashevis
@Nicholas Je pense que mon exemple est exactement ce que vous recherchez, je suis tombé sur le même problème aujourd'hui. Les menus déroulants débordent mais le premier niveau ne s'enroule pas.
John

Réponses:

107

La propriété CSS a display: inline-blockété conçue pour répondre à ce besoin. Vous pouvez en lire un peu ici: http://robertnyman.com/2010/02/24/css-display-inline-block-why-it-rocks-and-why-it-sucks/

Voici un exemple de son utilisation. Les éléments clés sont que l' rowélément a white-space: nowrapet les celléléments ont display: inline-block. Cet exemple devrait fonctionner sur la plupart des principaux navigateurs; un tableau de compatibilité est disponible ici: http://caniuse.com/#feat=inline-block

<html>
<body>
<style>

.row {
    float:left;
    border: 1px solid yellow;
    width: 100%;
    overflow: auto;
    white-space: nowrap;
}

.cell {
    display: inline-block;
    border: 1px solid red;
    width: 200px;
    height: 100px;
}
</style>

<div class="row">
    <div class="cell">a</div>
    <div class="cell">b</div>
    <div class="cell">c</div>
</div>


</body>
</html>
Calvin
la source
1
Ajoutez <!DOCTYPE html>ou <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">en haut du HTML pour que IE ne passe pas par défaut en mode bizarreries.
Cees Timmerman
4
Remarque: j'avais mes divs de type cellule configurés avec float: left, et cela a forcé le style calculé à être block, au lieu de inline-block. Il a fallu du temps pour comprendre, alors j'ai pensé qu'il était préférable de partager cela.
Steve Hibbert
Cela ne fonctionne pas avec la dernière cellule float: right, n'est-ce pas?
Andy
3
Ce n'est pas vraiment un exemple de la façon d'empêcher les div flottants de s'enrouler - vous venez de libérer les cellules. J'ai une mise en page avec des flotteurs gauche et droit, donc je ne peux pas me débarrasser des flotteurs pour résoudre le problème d'emballage.
Andy
Haha, assez juste. C'est une distinction pédante, mais vous avez raison. Je n'ai pas résolu "empêcher les div flottants de s'enrouler", j'ai résolu la vraie question du demandeur "comment faire fonctionner ma mise en page". Pour répondre à la première: je suis raisonnablement sûr qu'il n'y a aucun moyen d'empêcher les div flottants de s'enrouler. Tout comme le demandeur, vous devrez trouver une manière différente d'encoder la mise en page que vous décrivez.
Calvin
32

Vous voulez définir min-widthsur la ligne afin que lorsque le navigateur est redimensionné, il ne passe pas en dessous et ne s'enroule pas.

farooq
la source
1
Cela fonctionnerait même avec des flotteurs. Je pense que c'est la vraie réponse.
Danon
2
D'accord avec @Danon - cela fonctionne alors que le bloc en ligne a introduit des problèmes d'alignement vertical.
dlchambers
1
Dépend de vos besoins. Cela empêche les div flottants de s'habiller lorsque la page est redimensionnée, mais le demandeur a déclaré "Je ne veux pas spécifier la largeur de la ligne, la largeur devrait automatiquement être la largeur de ses cellules enfants". La spécification manuelle de la largeur nécessite un travail en double, car vous devez calculer la largeur totale de la ligne. Pire encore, si vos cellules sont de largeur variable (par exemple, parce qu'elles sont dimensionnées à une ligne de texte à l'intérieur), le calcul du total peut être peu pratique ou impossible.
Calvin
-1; Cela va à l'encontre de ce que l'OP a spécifiquement déclaré dans sa question, à savoir ne pas avoir à spécifier la largeur. +1 au commentaire de Calvin ci-dessus.
Teodor Sandu
4

Après avoir lu la réponse de John, j'ai découvert que ce qui suit semblait fonctionner pour nous (ne nécessitait pas de spécifier la largeur):

<style>
.row {
    float:left;
    border: 1px solid yellow;
    overflow: visible;
    white-space: nowrap;
}

.cell {
    display: inline-block;
    border: 1px solid red;
    height: 100px;
}
</style>

<div class="row">
    <div class="cell">hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello </div>
    <div class="cell">hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello </div>
    <div class="cell">hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello </div>
</div>
Kevin LeBlanc
la source
Cela a résolu un problème que j'avais avec les divs déplaçables sur l'iphone. Lorsque les divs contenaient plus d'un mot et qu'ils étaient déplacés vers le bord de l'écran, le div s'enroulait pour qu'il y ait un mot sur l'une ou l'autre ligne. Quoi qu'il en soit a overflow: visible; white-space: nowrap;fait l'affaire pour moi. Merci!
TryHarder
4
Cela a fonctionné parce qu'il a dégonflé les cellules. Pas vraiment une solution pour empêcher les div flottants de s'enrouler
Andy
1

La seule façon dont j'ai réussi à faire cela est d'utiliser overflow: visible;et width: 20000px;sur l'élément parent. Il n'y a aucun moyen de faire cela avec CSS niveau 1 que je connaisse et j'ai refusé de penser que je devrais aller complètement avec CSS niveau 3. L'exemple ci-dessous contient 18 menus qui s'étendent au-delà de mon écran LCD de résolution 1920x1200 , si votre écran est plus grand, dupliquez simplement les éléments de menu du premier niveau ou redimensionnez simplement le navigateur. Alternativement et avec des niveaux légèrement inférieurs de compatibilité du navigateur, vous pouvez utiliser des requêtes multimédias CSS3.

Voici un exemple de démonstration complète de copier / coller ...

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>XHTML5 Menu Demonstration</title>
<style type="text/css">
* {border: 0; box-sizing: content-box; color: #f0f; font-size: 10px; margin: 0; padding: 0; transition-property: background-color, background-image, border, box-shadow, color, float, opacity, text-align, text-shadow; transition-duration: 0.5s; white-space: nowrap;}
a:link {color: #79b; text-decoration: none;}
a:visited {color: #579;}
a:focus, a:hover {color: #fff; text-decoration: underline;}
body {background-color: #444; overflow-x: hidden;}
body > header {background-color: #000; height: 64px; left: 0; position: absolute; right: 0; z-index: 2;}
body > header > nav {height: 32px; margin-left: 16px;}
body > header > nav a {font-size: 24px;}
main {border-color: transparent; border-style: solid; border-width: 64px 0 0; bottom: 0px; left: 0; overflow-x: hidden !important; overflow-y: auto; position: absolute; right: 0; top: 0; z-index: 1;}
main > * > * {background-color: #000;}
main > section {float: left; margin-top: 16px; width: 100%;}
nav[id='menu'] {overflow: visible; width: 20000px;}
nav[id='menu'] > ul {height: 32px;}
nav[id='menu'] > ul > li {float: left; width: 140px;}
nav[id='menu'] > ul > li > ul {background-color: rgba(0, 0, 0, 0.8); display: none; margin-left: -50px; width: 240px;}
nav[id='menu'] a {display: block; height: 32px; line-height: 32px; text-align: center; white-space: nowrap;}
nav[id='menu'] > ul {float: left; list-style:none;}
nav[id='menu'] ul li:hover ul {display: block;}
p, p *, span, span * {color: #fff;}
p {font-size: 20px; margin: 0 14px 0 14px; padding-bottom: 14px; text-indent: 1.5em;}
.hidden {display: none;}
.width_100 {width: 100%;}
</style>
</head>

<body>

<main>
<section style="height: 2000px;"><p>Hover the first menu at the top-left.</p></section>
</main>

<header>
<nav id="location"><a href="">Example</a><span> - </span><a href="">Blog</a><span> - </span><a href="">Browser Market Share</a></nav>
<nav id="menu">
<ul>
<li><a href="" tabindex="2">Menu 1 - Hover</a>
<ul>
<li><a href="" tabindex="2">Menu 1 B</a></li>
<li><a href="" tabindex="2">Menu 1 B</a></li>
<li><a href="" tabindex="2">Menu 1 B</a></li>
<li><a href="" tabindex="2">Menu 1 B</a></li>
<li><a href="" tabindex="2">Menu 1 B</a></li>
<li><a href="" tabindex="2">Menu 1 B</a></li>
<li><a href="" tabindex="2">Menu 1 B</a></li>
<li><a href="" tabindex="2">Menu 1 B</a></li>
</ul>
</li>
<li><a href="" tabindex="2">Menu 2</a></li>
<li><a href="" tabindex="2">Menu 3</a></li>
<li><a href="" tabindex="2">Menu 4</a></li>
<li><a href="" tabindex="2">Menu 5</a></li>
<li><a href="" tabindex="2">Menu 6</a></li>
<li><a href="" tabindex="2">Menu 7</a></li>
<li><a href="" tabindex="2">Menu 8</a></li>
<li><a href="" tabindex="2">Menu 9</a></li>
<li><a href="" tabindex="2">Menu 10</a></li>
<li><a href="" tabindex="2">Menu 11</a></li>
<li><a href="" tabindex="2">Menu 12</a></li>
<li><a href="" tabindex="2">Menu 13</a></li>
<li><a href="" tabindex="2">Menu 14</a></li>
<li><a href="" tabindex="2">Menu 15</a></li>
<li><a href="" tabindex="2">Menu 16</a></li>
<li><a href="" tabindex="2">Menu 17</a></li>
<li><a href="" tabindex="2">Menu 18</a></li>
</ul>
</nav>
</header>

</body>
</html>
John
la source
Quand j'utilise la réponse votée et la remplace width:100%par width:1000pxelle fonctionne pour moi
Nick.McDermaid
@ Nick.McDermaid J'ai utilisé 20K pixels pour une raison, avec des écrans 4K qui sortent, vous savez qu'il y aura finalement 8K et ainsi de suite, il est donc préférable de travailler avec un nombre incroyablement élevé pour le faire fonctionner pendant ces années supplémentaires jusqu'à ce que les écrans soient plus hauts -résolution que la vie elle-même. ;-)
John
Compris ... Je suis juste content de l'avoir arrêté. CSS-it me rend fou même avec les outils F12. Je ne sais pas comment quelqu'un a pu faire quoi que ce soit sans eux.
Nick.McDermaid
1
Pour référence future: l'utilisation d'une largeur / hauteur énorme est très inefficace car le navigateur stocke toujours une grande boîte inutile en mémoire. Définissez le conteneur sur white-space: nowrap;et les enfants sur display: inline-block;comme déjà dit dans d'autres réponses (ou revenez à display: table;et display: table-cell;).
gyo
main > * > * {background-color: #000;}O_o
theflowersoftime
0

Pour moi (en utilisant bootstrap), la seule chose qui fonctionnait était de définir display:absolute;z-index:1la dernière cellule.

Spikolynn
la source
1
display:absoluten'est pas valide CSS
caiosm1005
-1

J'ai eu un problème un peu similaire où une zone délimitée se composait d'une image dans un flottant: bloc gauche et un bloc de texte non flottant. La zone a une largeur fluide. Le texte serait, de par sa conception, enveloppé le long du côté droit de l'image. Le problème était que le texte commençait par une balise <h2>, dont le premier mot est le petit mot "From". Lorsque j'ai redimensionné la fenêtre à une largeur plus petite, le texte non flottant, pour une certaine plage de largeurs, ne laisserait que le mot "De" en haut de la zone d'habillage, le reste du texte ayant été pressé sous le flottant bloquer. Ma solution a été d'agrandir le premier mot de la balise, en remplaçant l'espace qui le suivait par ce code, <span style = "opacity: 0;"> x </span>. L'effet était de créer le premier mot, au lieu de "From", "FromxNextWord", où le "x", étant invisible, ressemblait à un espace. Maintenant, mon premier mot était assez gros pour ne pas être abandonné par le reste du bloc de texte.

Jim
la source