A caixa de texto de entrada HTML com uma largura de 100% transborda as células da tabela

106

Alguém sabe por que os elementos de entrada com largura de 100% ultrapassam a borda das células da tabela.

No exemplo simples abaixo, a caixa de entrada ultrapassa a borda das células da tabela e o resultado é horrível. Isso foi testado e acontece da mesma forma em: Firefox, IE7 e Safari.

Isso faz sentido para você? Estou faltando alguma coisa, você sabe sobre uma possível solução?

<!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
fonte
1
Gostaria de sugerir que, se você está apenas usando uma tabela para apresentar as entradas, você pode passar a usar um formcom as labels e inputs dentro de um ulou ol. que é, pelo menos, um pouco mais semântico. Certamente, você deve usar um form, mesmo que continue com o table.
David diz para restabelecer Monica de

Respostas:

216

Você pode usar a box-sizingpropriedade CSS3 para incluir o preenchimento externo e a borda:

input[type="text"] {
     width: 100%; 
     box-sizing: border-box;
     -webkit-box-sizing:border-box;
     -moz-box-sizing: border-box;
}
pricco
fonte
1
É triste dizer, mas infelizmente o IE 7 não lida corretamente com o dimensionamento da caixa. Tente o seguinte no IE 7 ... css3.info/preview/box-sizing ou consulte css-tricks.com/box-sizing
AnthonyVO
@AnthonyVO: true, a única solução alternativa para o IE7 é adicionar CSS específico para ele usando comentários condicionais do IE <!--[if lt IE 8]>einput[type="text"] {width:95%}
Marco Demaio
24

O valor da largura não leva em consideração a borda ou o preenchimento:

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

Você obtém 2 px de preenchimento em cada lado, mais 1 px de borda em cada lado.
100% + 2 * (2px + 1px) = 100% + 6px, que é mais do que 100% de conteúdo filho que o td pai tem.

Você tem a opção de:

  • Qualquer configuração box-sizing: border-box;conforme a resposta de @pricco ;
  • Ou usando margem 0 e preenchimento (evitando o tamanho extra).
ANeves
fonte
na sequência da resposta do Sr pts, você pode definir o preenchimento e a borda para 0px, então o 100% deve funcionar.
Mauro
Na verdade, mesmo sem definir qualquer preenchimento para td - muito bem adicionado.
ANeves,
1
Além disso, se o preenchimento criar um problema, é possível usar text-indentpara simular o preenchimento à frente da borda do texto e line-heightpara o preenchimento vertical (embora manter o preenchimento vertical não afetaria a largura de qualquer maneira).
David diz reintegrar Monica
14

O problema com coisas assim width:95%;é que elas não parecem certas em layouts largos e flexíveis (porque 5% podem ter 30 pixels).

As soluções a seguir funcionam muito bem para mim (testado no 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>

(adicionadas as cores para tornar mais fácil notar o preenchimento correto)

O truque é envolver a entrada com dois divs, o externo tem uma margem de 3px (o que o torna 3px menor que o td), o interno tem um preenchimento de 3px. Isso torna a entrada 6px menor que o td, que é o que você queria para começar.

Não tenho certeza sobre a mecânica disso, mas funciona.

Neste exemplo simples, ele também funciona com apenas um único div com margem direita 6. No entanto, no caso do meu aplicativo da web, apenas a solução acima funciona.

<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
fonte
Funciona (voto positivo +1). Estranhamente, eu inseri algum texto antes de cada <input> e adicionei "white-space: nowrap" para mantê-los na mesma linha, então os três <inputs> estouraram as células da tabela, se eu remover "white-space: nowrap" tudo funciona novamente. Esquisito.
Jose Manuel Abarca Rodríguez
8

O problema foi explicado anteriormente, por isso vou apenas reiterar: a largura não leva em conta a borda e o enchimento. Uma resposta possível a isso não discutida, mas que descobri que me ajudou bastante, é embrulhar suas entradas. Aqui está o código e explicarei como isso ajuda em um segundo:

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

O DIV que envolve o INPUT não tem preenchimento nem borda. Esta é a solução. Um DIV se expandirá para o tamanho de seu contêiner, mas também respeitará a borda e o preenchimento. Agora, o INPUT não terá problemas para expandir para o tamanho de seu contêiner, pois ele é sem borda e sem almofada. Observe também que o DIV tem seu overflow definido como oculto. Parece que, por padrão, os itens podem cair fora de seu contêiner com o estouro padrão de visível. Isso apenas garante que a entrada permaneça dentro de seu contêiner e não tente penetrar.

Eu testei isso no Chrome e no Fire Fox. Ambos parecem respeitar bem esta solução.

ATUALIZAÇÃO : como acabei de receber uma votação negativa aleatória, gostaria de dizer que a melhor maneira de lidar com o estouro é com o atributo box-sizing CSS3, conforme descrito por 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;
}

Isso parece ser muito bem suportado pelos principais navegadores e não é "hacky" como o truque de estouro. Existem, no entanto, alguns problemas menores nos navegadores atuais com essa abordagem (consulte http://caniuse.com/#search=box-sizing Problemas conhecidos).

David Peterson
fonte
3
Uma nota curta: com overflow: hidden;o conteúdo ainda 'cutucado' para fora da caixa exatamente da mesma maneira, mas é truncado em vez de ser mostrado - então não se sobrepõe a outro conteúdo.
ANeves
2

Eu sei que esta pergunta tem 3 anos, mas o problema ainda persiste para os navegadores atuais e as pessoas ainda estão vindo aqui. A solução por enquanto é calc () :

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

É compatível com a maioria dos navegadores modernos.

trojan
fonte
1

O problema é devido ao modelo da caixa do elemento de entrada. Recentemente, encontrei uma boa solução para o problema ao tentar manter minha entrada em 100% para dispositivos móveis.

Envolva sua entrada com outro elemento, um div, por exemplo. Em seguida, aplique o estilo que você deseja para sua entrada a esse div do wrapper. Por exemplo:

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

Forneça um preenchimento de canto arredondado de .input-wrapper, etc., o que quiser para sua entrada e, em seguida, forneça a largura de entrada 100%. Você tem sua entrada preenchida com uma borda, etc, mas sem o estouro irritante!

hallodom
fonte
1

Corrigi esse problema começando com a resposta de @allodom. Todas as minhas entradas estavam contidas em li, então tudo que eu tive que fazer foi definir o estouro de li: oculto para remover esse estouro de entrada em excesso.

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

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

em vez desta luta de margem apenas faça

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

desta forma a borda da célula fica visível e você pode controlar a cor de fundo da linha

bortunac
fonte
0

Retire o "http://www.w3.org/TR/html4/loose.dtd" da declaração DOCTYPE e resolva o seu problema.

Felicidades! :)

Lucian
fonte
Você quer dizer usar http://www.w3.org/TR/html4/strict.dtdStrict? ref. w3.org/QA/2002/04/valid-dtd-list.html De qualquer forma, esta não é uma opção, pois alterar o DOCTYPE agora provavelmente afetaria a renderização de muitas outras coisas nas páginas da web.
Marco Demaio
0

Com algum Javascript, você pode obter a largura exata do TD que o contém e atribuí-la diretamente ao elemento de entrada.

O que se segue é javascript bruto, mas jQuery o tornaria mais limpo ...

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

Os problemas com esta solução são:

1) Se você tiver suas entradas contidas em outro elemento, como um SPAN, precisará fazer um loop e encontrar o TD, porque elementos como os SPANs envolverão a entrada e mostrarão seu tamanho, em vez de serem limitados ao tamanho do TD.

2) Se você tiver preenchimento ou margens adicionados em níveis diferentes, talvez seja necessário subtrair explicitamente de [pEl.offsetWidth]. Dependendo de sua estrutura HTML, isso pode ser calculado.

3) Se as colunas da tabela forem dimensionadas dinamicamente, alterar o tamanho de um elemento fará com que a tabela reflua em alguns navegadores e você poderá obter um efeito escalonado conforme "corrige" sequencialmente os tamanhos de entrada. A solução é atribuir larguras específicas para a coluna como porcentagens ou pixels OU coletar as novas larguras e defini-las depois. Veja o código abaixo ..

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

Resolvi o problema aplicando box-sizing:border-box; para as próprias células da tabela, além de fazer o mesmo com a entrada e o wrapper.

Vanco
fonte
0

Eu resolvi o problema usando este

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

Eu geralmente defino a largura de minhas entradas para 99% para corrigir isso:

input {
    width: 99%;
}

Você também pode remover os estilos padrão, mas isso tornará menos óbvio que se trata de uma caixa de texto. No entanto, vou mostrar o código para isso de qualquer maneira:

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

Ad @ m

kirb
fonte
-2

O problema reside no border-widthelemento de entrada. Em breve, tente definir o margin-leftdo elemento de entrada como -2px.

table input {
  margin-left: -2px;
}
burek pekaric
fonte
acho que não. que apenas desloca a caixa para a esquerda e destrói a margem esquerda
cc jovem