Puis-je empêcher les zones de texte de 100% de largeur de s'étendre au-delà de leurs conteneurs?

181

Disons que j'ai une zone de texte que je veux remplir une ligne entière. Je lui donnerais un style comme celui-ci:

input.wide {display:block; width: 100%}

Cela pose des problèmes car la largeur est basée sur le contenu de la zone de texte. Les zones de texte ont une marge, des bordures et un remplissage par défaut, ce qui rend une zone de texte de 100% de largeur plus grande que son conteneur.

Par exemple, ici à droite:

entrez la description de l'image ici

Existe-t-il un moyen de faire en sorte qu'une zone de texte remplisse la largeur de son conteneur sans s'étendre au-delà?

Voici un exemple de HTML pour montrer ce que je veux dire:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Untitled Page</title>
    <style type="text/css">
        #outer{border: 1px solid #000; width: 320px; margin: 0px;padding:0px}
        #inner{margin: 20px; padding: 20px; background: #999;border: 1px solid #000;}
        input.wide {display:block; margin: 0px}
        input.normal {display:block; float: right}
    </style>
</head>
<body>
    <div id="outer">
        <div id="inner">
            <input type="text" class="wide" />
            <input type="text" class="normal" />
            <div style="clear:both;"></div>
        </div>
    </div>
</body>
</html>

Si cela est exécuté, vous pouvez voir en regardant la zone de texte "normale" que la zone de texte "large" dépasse du conteneur. La zone de texte "normale" flotte jusqu'au bord réel du conteneur. J'essaie de faire en sorte que la zone de texte "large" remplisse son conteneur, sans s'étendre au-delà du bord comme la zone de texte "normale" l'est.

Dan Herbert
la source

Réponses:

87

Ce que vous pouvez faire est de supprimer les "extras" par défaut sur input:

input.wide {display:block; width:100%;padding:0;border-width:0}

Cela gardera l' inputintérieur de son conteneur. Maintenant , si vous ne voulez les frontières, envelopper l' inputun div, avec les frontières fixées sur la div(cette façon , vous pouvez retirer le display:blockdu inputtrop). Quelque chose comme:

<div style="border:1px solid gray;">
 <input type="text" class="wide" />
</div>

Modifier: une autre option consiste à, au lieu de supprimer le style du input, de le compenser dans le wrapped div:

input.wide {width:100%;}

<div style="padding-right:4px;padding-left:1px;margin-right:2px">
  <input type="text" class="wide" />
</div>

Cela vous donnera des résultats quelque peu différents dans différents navigateurs, mais ils ne chevaucheront pas le conteneur. Les valeurs du div dépendent de la taille de la bordure sur le inputet de l'espace souhaité entre le inputet la bordure.

Hilbrand Bouwkamp
la source
3
C'est une solution très créative. Le seul problème que j'ai avec cela est que je ne peux pas définir un contour sur la zone de texte lorsqu'elle obtient le focus, sauf si j'utilise JavaScript pour changer la bordure de la div wrapper.
Dan Herbert
@DanHerbert, vous avez raison, c'est une faille UX majeure de cette méthode
Baumr
275

Existe-t-il un moyen de faire en sorte qu'une zone de texte remplisse la largeur de son conteneur sans s'étendre au-delà?

Oui: en utilisant la propriété CSS3 'box-sizing: border-box', vous pouvez redéfinir ce que signifie 'width' pour inclure le remplissage et la bordure externes.

Malheureusement, parce qu'il s'agit de CSS3, le support n'est pas très mature et comme le processus de spécification n'est pas encore terminé, il a entre-temps différents noms temporaires dans les navigateurs. Alors:

input.wide {
    width: 100%;
    box-sizing: border-box;
    -moz-box-sizing: border-box;
    -webkit-box-sizing: border-box;
}

L'alternative à l'ancienne est simplement de mettre une quantité de 'padding-right' sur l'élément englobant <div> ou <td> égale à environ combien de marge / bordure supplémentaire à gauche et à droite dans 'px' vous pensez que les navigateurs vont donnez votre avis. (Généralement 6px pour IE <8.)

bobince
la source
Cela fonctionnerait très bien, sauf que je ne peux pas l'utiliser car je cible les appareils mobiles qui ne le prendront probablement pas en charge pendant des années. : - \
Dan Herbert
20
Je pense que les appareils mobiles bénéficieront d'un support HTML5 complet avant les ordinateurs.
Mariano Cavallo
4
@Kindred: certainement pas si vous incluez IEMobile et Blackberry.
bobince
1
Cela a un excellent support pour les navigateurs de bureau, cependant: quirksmode.org/css/contents.html
logan
2
Comment m'a-t-il fallu autant de temps pour trouver cette super compote de beurre ??? Pouvons-nous en faire la réponse acceptée?
streetlogics
14

Cela a résolu le problème pour moi!

Sans avoir besoin d'un div externe. Appliquez-le simplement à votre zone de texte donnée.

box-sizing: border-box; 

Avec cette propriété "Les propriétés de largeur et de hauteur (et les propriétés min / max) incluent le contenu, le remplissage et la bordure, mais pas la marge"

Voir la description de la propriété à w3schools .

J'espère que cela aide quelqu'un!

Jack Trowbridge
la source
Merveilleusement simple! THX!
nurider
10

Je viens de rencontrer ce problème moi-même, et la seule solution que j'ai pu trouver qui fonctionnait dans tous mes navigateurs de test (IE6, IE7, Firefox) était la suivante:

  1. Enveloppez le champ de saisie dans deux DIV séparés
  2. Réglez le DIV extérieur sur une largeur de 100%, cela empêche notre conteneur de déborder du document
  3. Mettez un remplissage dans le DIV intérieur du montant exact pour compenser le débordement horizontal de l'entrée.
  4. Définissez un remplissage personnalisé sur l'entrée afin qu'il déborde du même montant que je l'ai autorisé dans le DIV interne

Le code:

<div style="width: 100%">
    <div style="padding-right: 6px;">
        <input type="text" style="width: 100%; padding: 2px; margin: 0;
                                  border : solid 1px #999" />
    </div>
</div>

Ici, le débordement horizontal total pour l'élément d'entrée est de 6px - 2x (padding + border) - nous définissons donc un padding-right pour le DIV interne de 6px.

Tobias Cohen
la source
ajouter à l'élément d'entrée un remplissage de 8px et cela ne fonctionne plus
JuHwon
7

La prise en charge du dimensionnement des boîtes est plutôt bonne en fait: http://caniuse.com/#search=box-sizing

Donc, à moins que vous ne cibliez IE7, vous devriez être en mesure de résoudre ce type de problèmes en utilisant cette propriété. Un calque tel que sass ou moins facilite la gestion des règles préfixées comme ça, btw.

chikamichi
la source
3

En fait, c'est parce que CSS définit 100% par rapport à toute la largeur du conteneur, y compris ses marges, ses bordures et son remplissage; cela signifie que l'espace disponible. à son contenu est une quantité inférieure à 100%, sauf si le conteneur n'a pas de marges, de bordures ou de remplissage.

Ceci est contre-intuitif et largement considéré par beaucoup comme une erreur avec laquelle nous sommes maintenant coincés . Cela signifie effectivement que les dimensions% ne conviennent à rien d'autre qu'un conteneur de niveau supérieur, et même dans ce cas, uniquement s'il n'a pas de marges, de bordures ou de remplissage.

Notez que les marges, les bordures et le remplissage du champ de texte sont inclus dans la taille CSS spécifiée pour lui - c'est le conteneur qui gâche les choses.

J'ai assez bien contourné ce problème en utilisant 98%, mais c'est une solution loin d'être parfaite, car les champs d'entrée ont tendance à être encore plus courts à mesure que le conteneur s'agrandit.


EDIT: Je suis tombé sur cette question similaire - je n'ai jamais essayé la réponse donnée, et je ne sais pas avec certitude si cela s'applique à votre problème, mais il semble que ce sera le cas.

Lawrence Dol
la source
1

Une solution qui peut fonctionner (cela fonctionne pour moi) est d'appliquer une marge négative à l'entrée (zone de texte) ... ou une largeur fixe pour ie7 ou de supprimer le support ie7. Cela donne une largeur de pixel parfaite .. Pour moi, c'est 7, donc j'ai ajouté 3 et 4 mais c'est toujours parfait.

J'ai eu le même problème et j'ai détesté avoir des div supplémentaires pour la frontière, etc.

Voici donc ma solution qui semble fonctionner!

Vous devez utiliser une feuille de style ie7 uniquement pour éviter les starhacks.

input.text{
    background-color: #fbfbfb;
    border : solid #eee 1px;
    width: 100%;
    -box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    height: 32px;

    *line-height:32px;
    *margin-left:-3px;
    *margin-right:-4px;
    display: inline;   
    padding: 0px 0 0 5px;

}
GorillaApe
la source
1

Si vous ne pouvez pas utiliser, box-sizing:border-boxvous pouvez essayer de supprimer le width:100%et de mettre un très grand sizeattribut dans l' <input>élément, l'inconvénient est cependant que vous devez modifier le html, et ne pouvez pas le faire avec CSS uniquement:

<input size="1000"></input>
siddhadev
la source
0

Si vous n'avez pas besoin de le faire de manière dynamique (par exemple, votre formulaire a une largeur fixe), vous pouvez simplement définir la largeur des <input>éléments enfants sur la largeur de leur conteneur moins les décorations telles que le remplissage, la marge, la bordure, etc.:

 // the parent div here has a width of 200px:
.form-signin input[type="text"], .form-signin input[type="password"], .form-signin input[type="email"], .form-signin input[type="number"] {
  font-size: 16px;
  height: auto;
  display: block;
  width: 280px;
  margin-bottom: 15px;
  padding: 7px 9px;
}
Avishai
la source
0

Si vous ne pouvez pas utiliser le dimensionnement de la boîte (par exemple, lorsque vous convertissez du HTML en PDF à l'aide d'iText). Essaye ça:

CSS

.input-wrapper { border: 1px solid #ccc; padding: 0 5px; min-height: 20px; } 
.input-wrapper input[type=text] { border: none; height: 20px; width: 100%; padding: 0; margin: 0; }

HTML

<div class="input-wrapper">
     <input type="text" value="" name="city"/>
</div>
Robertad
la source
0

Cela marche:

<div>
    <input type="text" 
        style="margin: 5px; padding: 4px; border: 1px solid; 
        width: 200px; width: calc(100% - 20px);">
</div>

La première «largeur» est une règle de secours pour les anciens navigateurs.

Mo'in Creemers
la source
0

Stylez simplement l'entrée pour qu'elle soit décalée pour le remplissage supplémentaire. Dans l'exemple suivant, le remplissage de l'entrée serait de 10 pixels à gauche et à droite pour un décalage de remplissage total de 20 pixels:

input[type=text]{
   width: calc(100% - 20px);
}
quinlo
la source