La zone de texte d'entrée HTML d'une largeur de 100% dépasse les cellules du tableau

106

Quelqu'un sait-il pourquoi les éléments d'entrée d'une largeur de 100% passent au-dessus de la bordure des cellules du tableau?

Dans l'exemple simple ci-dessous, passez sur la bordure des cellules du tableau, le résultat est horrible. Cela a été testé et cela se passe de la même manière sur: Firefox, IE7 et Safari.

Cela a-t-il un sens pour vous? Est-ce que je manque quelque chose, connaissez-vous une solution possible?

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">    
<html><head>    
   <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> <!-- don't use closing slash in meta tag, it breaks HTML4.01 transitional -->
   <title>Test input text in table</title>
   <style type="text/css">      
      table {border-top: 1px solid #ff0000; border-left: 1px solid #ff0000;}
      table td {border-right: 1px solid #00ff00; border-bottom: 1px solid #00ff00;}
      input[type="text"] {width: 100%;} /* removing this would make input not to go over cells border, but they would be too short, I want them to fit cells size */
   </style>    
</head><body>

<table cellpadding="0" cellspacing="0">
   <tr>
      <td><p>column one hello babe babe babe</p></td>
      <td><p>column two hello babe more</p></td>
      <td><p>column three hello babe more and more</p></td>
   </tr>
   <tr>
      <td><input type="text" value="test"></td>
      <td><input type="text" value="test"></td>
      <td><input type="text" value="test"></td>
   </tr>
</table>

</body></html>
Marco Demaio
la source
1
Je suggérerais que, si vous utilisez simplement un tableau pour présenter les entrées, vous pouvez passer à l'utilisation de a formavec les labels et inputs à l'intérieur de ulou ol. ce qui est, au moins légèrement plus sémantique. Cependant, vous devriez certainement utiliser a form, même si vous vous en tenez au table.
David dit de réintégrer Monica

Réponses:

216

Vous pouvez utiliser la box-sizingpropriété CSS3 pour inclure le remplissage externe et la bordure:

input[type="text"] {
     width: 100%; 
     box-sizing: border-box;
     -webkit-box-sizing:border-box;
     -moz-box-sizing: border-box;
}
Pricco
la source
1
Malheureusement, IE 7 ne gère pas correctement le dimensionnement des boîtes. Effectuez les opérations suivantes dans Internet Explorer 7 ... css3.info/preview/box-sizing ou voir css-tricks.com/box-sizing
AnthonyVO
@AnthonyVO: vrai, la seule solution de contournement pour IE7 est d'ajouter un CSS spécifique à l'aide de commentaires conditionnels IE <!--[if lt IE 8]>etinput[type="text"] {width:95%}
Marco Demaio
24

La valeur de la largeur ne prend pas en compte la bordure ou le remplissage:

http://www.htmldog.com/reference/cssproperties/width/

Vous obtenez 2 px de rembourrage de chaque côté, plus 1 px de bordure de chaque côté.
100% + 2 * (2px + 1px) = 100% + 6px, ce qui est plus que le contenu enfant à 100% du td parent.

Vous avez la possibilité de:

  • Soit le réglage box-sizing: border-box;selon la réponse de @ pricco ;
  • Ou en utilisant une marge et un remplissage 0 (en évitant la taille supplémentaire).
ANeves
la source
suite à la réponse Sr pts, vous pouvez définir le remplissage et la bordure à 0px, alors le 100% devrait fonctionner.
Mauro
En effet, même sans définir de rembourrage pour td - très bien ajouté.
ANeves
1
De plus, si le remplissage crée un problème, il est possible de l'utiliser text-indentpour simuler le remplissage avant le bord d'attaque du texte, et line-heightpour le remplissage vertical (bien que conserver le remplissage vertical n'affecterait pas la largeur de toute façon).
David dit de réintégrer Monica
14

Le problème avec des choses comme width:95%;c'est qu'elles n'ont pas l'air correct dans des mises en page larges et flexibles (car 5% peuvent alors être comme 30 pixels).

Les solutions suivantes fonctionnent très bien pour moi (testées dans Firefox, IE 9, Safari):

<table style="background-color: blue; width: 100%;" cellpadding="0" cellspacing="0">
<tr>
    <td style="background-color: red;   padding: 3px;">
        <div style="margin-right: 3px;">
            <div style="padding-right: 3px;">
                <input type="text" style="width:100%;">
            </div>
        </div>
    </td>
    <td style="background-color: purple;   padding: 3px;">
        <div style="margin-right: 3px;">
            <div style="padding-right: 3px;">
                <input type="text" style="width:100%;">
            </div>
        </div>
    </td>
    <td style="background-color: green;   padding: 3px;">
        <div style="margin-right: 3px;">
            <div style="padding-right: 3px;">
                <input type="text" style="width:100%;">
            </div>
        </div>
    </td>
</tr>
</table>

(ajout des couleurs pour faciliter la détection du bon rembourrage)

L'astuce consiste à envelopper l'entrée avec deux divs, l'extérieur a une marge de 3px (ce qui le rend 3px plus petit que le td), l'intérieur a un rembourrage de 3px. Cela rend l'entrée 6px plus petite que le td, ce que vous vouliez commencer.

Je ne suis pas sûr de la mécanique de cela, mais cela fonctionne.

Dans cet exemple simple, cela fonctionne également avec un seul div avec une marge de droite 6. Cependant, dans le cas de mon application Web, seule la solution ci-dessus fonctionne.

<table style="background-color: blue; width: 100%;" cellpadding="0" cellspacing="0">
<tr>
    <td style="background-color: red;   padding: 3px;">
        <div style="margin-right: 6px;">
                <input type="text" style="width:100%;">
        </div>
    </td>
    <td style="background-color: purple;   padding: 3px;">
        <div style="margin-right: 6px;">
                <input type="text" style="width:100%;">
        </div>
    </td>
    <td style="background-color: green;   padding: 3px;">
        <div style="margin-right: 6px;">
                <input type="text" style="width:100%;">
        </div>
    </td>
</tr>
</table>
Andreas
la source
Cela fonctionne (voté +1). Étrangement, j'ai inséré du texte avant chaque <input> et ajouté "white-space: nowrap" pour les garder sur la même ligne, puis les trois <inputs> ont débordé les cellules du tableau, si je supprime tout "white-space: nowrap" fonctionne à nouveau. Bizarre.
Jose Manuel Abarca Rodríguez
8

Le problème a été expliqué précédemment donc je ne ferai que le répéter: la largeur ne prend pas en compte la bordure et le remplissage. Une réponse possible à cette question non discutée mais que j'ai trouvée m'a aidé à sortir un tas est de conclure vos entrées. Voici le code, et je vais vous expliquer comment cela aide dans une seconde:

<table>
  <tr>
    <td><div style="overflow:hidden"><input style="width:100%" type="text" name="name" value="hello world" /></div></td>
  </tr>
</table>

Le DIV encapsulant INPUT n'a pas de remplissage ni de bordure. Telle est la solution. Un DIV s'étendra à la taille de son conteneur, mais il respectera également la bordure et le remplissage. Désormais, INPUT n'aura aucun problème à s'étendre à la taille de son conteneur car il est sans bordure et sans pad. Notez également que le DIV a son débordement défini sur masqué. Il semble que par défaut, les éléments peuvent tomber en dehors de leur conteneur avec le débordement par défaut de visible. Cela garantit simplement que l'entrée reste à l'intérieur de son conteneur et ne tente pas de pénétrer.

J'ai testé cela dans Chrome et dans Fire Fox. Les deux semblent bien respecter cette solution.

MISE À JOUR : Puisque je viens de recevoir un vote défavorable aléatoire, je voudrais dire qu'une meilleure façon de gérer le débordement est avec l'attribut CSS3 box-sizing tel que décrit par pricco:

.myinput {
    -moz-box-sizing: border-box;
    -webkit-box-sizing: border-box;
    -ms-box-sizing: border-box;
    -o-box-sizing: border-box;
    box-sizing: border-box;
}

Cela semble être assez bien pris en charge par les principaux navigateurs et n'est pas "piraté" comme l'astuce du débordement. Il existe cependant quelques problèmes mineurs sur les navigateurs actuels avec cette approche (voir http://caniuse.com/#search=box-sizing Problèmes connus).

David Peterson
la source
3
Une note courte: avec overflow: hidden;le contenu toujours `` pousse '' à l'extérieur de la boîte exactement de la même manière, mais il est tronqué au lieu d'être affiché - il ne chevauche donc pas d'autres contenus.
ANeves
2

Je sais que cette question date de 3 ans mais le problème persiste pour les navigateurs actuels et les gens viennent toujours ici. La solution pour l'instant est calc () :

input {
    width: calc(100% - 12px); /* IE 9,10 , Chrome, Firefox */
    width: -webkit-calc(100% - 12px); /*For safari 6.0*/
}

Il est pris en charge par la plupart des navigateurs modernes.

troyen
la source
1

Le problème est dû au modèle de boîte d'élément d'entrée. J'ai récemment trouvé une bonne solution au problème en essayant de garder mon entrée à 100% pour les appareils mobiles.

Enveloppez votre entrée avec un autre élément, un div par exemple. Ensuite, appliquez le style que vous souhaitez pour votre entrée à ce div wrapper. Par exemple:

<div class="input-wrapper">
 <input type="text" />
</div>

.input-wrapper {
    border-raius:5px;
    padding:10px;
}
.input-wrapper input[type=text] {
    width:100%;
    font-size:16px;
}

Donnez un rembourrage de coin arrondi .input-wrapper, etc., tout ce que vous voulez pour votre entrée, puis donnez la largeur d'entrée de 100%. Votre entrée est bien rembourrée avec une bordure, etc. mais sans le débordement ennuyeux!

hallodome
la source
1

J'ai résolu ce problème en commençant par la réponse de @ hallodom. Toutes mes entrées étaient contenues dans des li, donc tout ce que j'avais à faire était de définir le débordement de li: masqué pour qu'il supprime ce débordement d'entrée en excès.

.ie7 form li {
  width:100%;
  overflow:hidden;
}

.ie7 input {
  width:100%;
}
chet
la source
1

au lieu de cette lutte de marge, faites simplement

input{
    width:100%;
    background:transparent !important;
}

de cette façon, la bordure de la cellule est visible et vous pouvez contrôler la couleur d'arrière-plan de la ligne

Bortunac
la source
0

Retirez le "http://www.w3.org/TR/html4/loose.dtd" de la déclaration DOCTYPE et cela résout votre problème.

À votre santé! :)

Lucian
la source
Voulez-vous dire en utilisant http://www.w3.org/TR/html4/strict.dtdStrict? réf. w3.org/QA/2002/04/valid-dtd-list.html Quoi qu'il en soit, ce n'est pas une option car changer le DOCTYPE maintenant aurait probablement un impact sur le rendu de nombreux autres stuf dans les pages Web.
Marco Demaio
0

Avec du Javascript, vous pouvez obtenir la largeur exacte du TD contenant, puis l'affecter directement à l'élément d'entrée.

Ce qui suit est du javascript brut mais jQuery le rendrait plus propre ...

var inputs = document.getElementsByTagName('input');
for (var i = 0; i < inputs.length; i++)
{
    var el = inputs[i];
    if (el.style.width == '100%')
    {
        var pEl = el.parentNode;  // Assumes the parent node is the TD...
        el.style.width = pEl.offsetWidth;
    }
}

Les problèmes avec cette solution sont:

1) Si vos entrées sont contenues dans un autre élément tel qu'un SPAN, vous devrez boucler et trouver le TD car des éléments comme SPAN vont envelopper l'entrée et montrer sa taille plutôt que d'être limités à la taille du TD.

2) Si vous avez ajouté un remplissage ou des marges à différents niveaux, vous devrez peut-être soustraire explicitement cela de [pEl.offsetWidth]. En fonction de votre structure HTML qui peut être calculée.

3) Si les colonnes du tableau sont dimensionnées dynamiquement, changer la taille d'un élément entraînera la redistribution du tableau dans certains navigateurs et vous pourriez obtenir un effet échelonné lorsque vous "corrigez" séquentiellement les tailles d'entrée. La solution consiste à attribuer des largeurs spécifiques à la colonne sous forme de pourcentages ou de pixels OU de collecter les nouvelles largeurs et de les définir après. Voir le code ci-dessous.

var inputs = document.getElementsByTagName('input');
var newSizes = [];
for (var i = 0; i < inputs.length; i++)
{
    var el = inputs[i];
    if (el.style.width == '100%')
    {
        var pEl = el.parentNode;  // Assumes the parent node is the TD...
        newSizes.push( { el: el, width: pEl.offsetWidth });
    }
}

// Set the sizes AFTER to avoid stepping...
for (var i = 0; i < newSizes.length; i++)
{
    newSizes[i].el.style.width = newSizes[i].width;
}
AnthonyVO
la source
0

J'ai résolu le problème en postulant box-sizing:border-box; aux cellules du tableau elles-mêmes, en plus de faire de même avec l'entrée et le wrapper.

Vanco
la source
0

J'ai résolu le problème en utilisant ceci

tr td input[type=text] {
  width: 100%;
  box-sizing: border-box;
  -webkit-box-sizing:border-box;
  -moz-box-sizing: border-box;
  background:transparent !important;
  border: 0px;
}
Kevin Muchwat
la source
-1

Je règle généralement la largeur de mes entrées à 99% pour résoudre ce problème:

input {
    width: 99%;
}

Vous pouvez également supprimer les styles par défaut, mais cela rendra moins évident qu'il s'agit d'une zone de texte. Cependant, je vais quand même montrer le code pour cela:

input {
    width: 100%;
    border-width: 0;
    margin: 0;
    padding: 0;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
}

Annonce @ m

Kirb
la source
-2

Le problème réside dans border-widthl'élément d'entrée. En bref, essayez de définir le margin-leftde l'élément d'entrée sur -2px.

table input {
  margin-left: -2px;
}
burek pekaric
la source
ne pense pas. qui déplace simplement la boîte vers la gauche et détruit la marge de gauche
cc young