El cuadro de texto de entrada HTML con un ancho de 100% desborda las celdas de la tabla

106

¿Alguien sabe por qué los elementos de entrada con un ancho del 100% pasan por encima del borde de las celdas de la tabla?

En el ejemplo simple a continuación, el cuadro de entrada pasa sobre el borde de las celdas de la tabla, el resultado es horrible. Esto fue probado y sucede de la misma manera en: Firefox, IE7 y Safari.

¿Tiene sentido para ti? ¿Me estoy perdiendo algo? ¿Conoce una posible solución?

<!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
fuente
1
Sugeriría que, si solo está usando una tabla para presentar las entradas, puede cambiar a usar a formcon labels y inputs dentro de a ulo ol. que es, al menos un poco más semántico. Ciertamente, sin embargo, debería usar un form, incluso si se queda con el table.
David dice reinstalar a Monica

Respuestas:

216

Puede usar la box-sizingpropiedad CSS3 para incluir el relleno y el borde externos:

input[type="text"] {
     width: 100%; 
     box-sizing: border-box;
     -webkit-box-sizing:border-box;
     -moz-box-sizing: border-box;
}
pricco
fuente
1
Es triste decirlo, pero desafortunadamente IE 7 no se ocupa del tamaño de la caja correctamente. Pruebe lo siguiente en IE 7 ... css3.info/preview/box-sizing o consulte css-tricks.com/box-sizing
AnthonyVO
@AnthonyVO: cierto, la única solución para IE7 es agregar CSS específico para él usando comentarios condicionales de IE <!--[if lt IE 8]>yinput[type="text"] {width:95%}
Marco Demaio
24

El valor de ancho no tiene en cuenta el borde o el relleno:

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

Obtienes 2 px de relleno en cada lado, más 1 px de borde en cada lado.
100% + 2 * (2px + 1px) = 100% + 6px, que es más que el 100% de contenido infantil que tiene el padre td.

Tienes la opción de:

  • Cualquiera de los ajustes box-sizing: border-box;según la respuesta de @ pricco ;
  • O usando margen 0 y relleno (evitando el tamaño extra).
ANeves
fuente
Además de la respuesta de Sr pts, puede establecer el relleno y el borde en 0px, entonces el 100% debería funcionar.
Mauro
De hecho, incluso sin configurar ningún relleno para td, muy bien agregado.
ANeves
1
Además, si el relleno crea un problema, es posible usarlo text-indentpara simular el relleno delante del borde de entrada del texto y line-heightpara el relleno vertical (aunque conservar el relleno vertical no afectaría el ancho de todos modos).
David dice reinstalar a Monica
14

El problema con este tipo de cosas width:95%;es que no se ven bien en diseños amplios y flexibles (porque el 5% puede ser como 30 píxeles).

Las siguientes soluciones funcionan muy bien para mí (probadas en 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>

(agregó los colores para que sea más fácil notar el relleno correcto)

El truco consiste en envolver la entrada con dos divs, el exterior tiene un margen de 3px (lo que lo hace 3px más pequeño que el td), el interior tiene un relleno de 3px. Esto hace que la entrada sea 6px más pequeña que el td, que es con lo que quería comenzar.

No estoy seguro de la mecánica de esto, pero funciona.

En este ejemplo simple, también funciona con un solo div con margen derecho 6. Sin embargo, en el caso de mi aplicación web, solo funciona la solución anterior.

<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
fuente
Funciona (voto positivo +1). Curiosamente, inserté algo de texto antes de cada <input> y agregué "white-space: nowrap" para mantenerlos en la misma línea, luego los tres <inputs> desbordaron las celdas de la tabla, si elimino "white-space: nowrap" todo funciona de nuevo. Extraño.
Jose Manuel Abarca Rodríguez
8

El problema se ha explicado anteriormente, así que solo reiteraré: el ancho no tiene en cuenta el borde y el relleno. Una posible respuesta a esto que no se discutió, pero que descubrí que me ayudó mucho, es envolver sus entradas. Aquí está el código y explicaré cómo esto ayuda en un segundo:

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

El DIV que envuelve la ENTRADA no tiene relleno ni tiene borde. Esta es la solucion. Un DIV se expandirá al tamaño de su contenedor, pero también respetará el borde y el relleno. Ahora, INPUT no tendrá problemas para expandirse al tamaño de su contenedor, ya que no tiene bordes ni almohadilla. También tenga en cuenta que el DIV tiene su desbordamiento configurado como oculto. Parece que, de forma predeterminada, los elementos pueden caer fuera de su contenedor con el desbordamiento predeterminado de visible. Esto solo asegura que la entrada permanezca dentro de su contenedor y no intente penetrar.

Probé esto en Chrome y en Fire Fox. Ambos parecen respetar bien esta solución.

ACTUALIZACIÓN : Ya que acabo de recibir un voto negativo al azar, me gustaría decir que una mejor manera de lidiar con el desbordamiento es con el atributo de tamaño de caja CSS3 como lo describe 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;
}

Esto parece estar bastante bien soportado por los principales navegadores y no es "hacky" como el truco de desbordamiento. Sin embargo, existen algunos problemas menores en los navegadores actuales con este enfoque (consulte http://caniuse.com/#search=box-sizing Problemas conocidos).

David Peterson
fuente
3
Una nota breve: con overflow: hidden;el contenido todavía 'asoma' hacia el exterior de la caja exactamente de la misma manera, pero se trunca en lugar de mostrarse, por lo que no se superpone a otro contenido.
ANeves
2

Sé que esta pregunta tiene 3 años, pero el problema persiste para los navegadores actuales y la gente sigue viniendo aquí. La solución por ahora es calc () :

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

Es compatible con la mayoría de los navegadores modernos.

troyano
fuente
1

El problema se debe al modelo de caja de elementos de entrada. Recientemente encontré una buena solución al problema al intentar mantener mi entrada al 100% para dispositivos móviles.

Envuelva su entrada con otro elemento, un div por ejemplo. Luego aplique el estilo que desee para su entrada al envoltorio div. Por ejemplo:

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

Proporcione .input-wrapper relleno de esquinas redondeadas, etc., lo que desee para su entrada, luego proporcione el ancho de entrada 100%. ¡Tiene su entrada bien acolchada con un borde, etc. pero sin el molesto desbordamiento!

alabanza
fuente
1

Solucioné este problema comenzando con la respuesta de @ hallodom. Todas mis entradas estaban contenidas dentro de li, por lo que todo lo que tenía que hacer era configurar el desbordamiento de li: oculto para eliminar ese desbordamiento de entrada en exceso.

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

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

en lugar de esta lucha por el margen, simplemente haz

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

de esta manera, el borde de la celda es visible y puede controlar el color de fondo de la fila

Bortunac
fuente
0

Saque "http://www.w3.org/TR/html4/loose.dtd" de la declaración DOCTYPE y solucione su problema.

¡Salud! :)

Lucian
fuente
¿Te refieres a usar http://www.w3.org/TR/html4/strict.dtdStrict? árbitro. w3.org/QA/2002/04/valid-dtd-list.html De todos modos, esta no es una opción porque cambiar el DOCTYPE ahora probablemente afectaría la representación de muchas otras cosas en las páginas web.
Marco Demaio
0

Con algunos Javascript puede obtener el ancho exacto del TD que lo contiene y luego asignarlo directamente al elemento de entrada.

Lo siguiente es javascript sin formato, pero jQuery lo haría más limpio ...

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

Los problemas con esta solución son:

1) Si tiene sus entradas contenidas en otro elemento como un SPAN, entonces necesitará hacer un bucle y encontrar el TD porque elementos como SPAN envolverán la entrada y mostrarán su tamaño en lugar de limitarse al tamaño del TD.

2) Si tiene relleno o márgenes agregados en diferentes niveles, puede que tenga que restarlo explícitamente de [pEl.offsetWidth]. Dependiendo de su estructura HTML que se puede calcular.

3) Si las columnas de la tabla tienen un tamaño dinámico, cambiar el tamaño de un elemento hará que la tabla vuelva a fluir en algunos navegadores y puede obtener un efecto escalonado a medida que "corrige" secuencialmente los tamaños de entrada. La solución es asignar anchos específicos a la columna como porcentajes o píxeles O recopilar los nuevos anchos y establecerlos después. Consulte el código a continuación.

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

Resolví el problema aplicando box-sizing:border-box; a las propias celdas de la tabla, además de hacer lo mismo con la entrada y el contenedor.

Vanco
fuente
0

Resolví el problema usando esto

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

Por lo general, establezco el ancho de mis entradas al 99% para solucionar esto:

input {
    width: 99%;
}

También puede eliminar los estilos predeterminados, pero eso hará que sea menos obvio que es un cuadro de texto. Sin embargo, mostraré el código para eso de todos modos:

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

Ad @ m

kirb
fuente
-2

El problema radica en border-widthel elemento de entrada. En breve, intente configurar el margin-leftdel elemento de entrada en -2px.

table input {
  margin-left: -2px;
}
burek pekaric
fuente
no lo creo. que simplemente desplaza la caja hacia la izquierda y destruye el margen izquierdo
cc young