<fieldset> redimensiona errado; parece ter `min-width: min-content 'irremovível


221

Problema

Eu tenho um <select>onde um dos seus <option>valores de texto é muito longo. Quero que o <select>redimensione para que nunca seja mais largo que seu pai, mesmo que precise cortar o texto exibido. max-width: 100%deveria fazer isso.

Antes de redimensionar:

a página antes do redimensionamento, mostrando todo o <code> selecione </code>

O que eu quero depois de redimensionar:

minha página desejada após o redimensionamento, com o <code> select </code> recortando seu conteúdo

Mas se você carregar este exemplo jsFiddle e redimensionar a largura do painel Resultado para ser menor que a largura do <select>, poderá ver que a seleção dentro da <fieldset>falha ao diminuir sua largura.

O que estou vendo após o redimensionamento:

minha página atual após o redimensionamento, com uma barra de rolagem

No entanto, a página equivalente com a em <div>vez de a<fieldset> é dimensionada corretamente. Você pode ver isso e testar suas alterações mais facilmente se tiver um <fieldset>e um <div>ao lado do outro em uma página . E se você excluir as <fieldset>tags ao redor , o redimensionamento funcionará. De <fieldset>alguma forma, a tag está causando o redimensionamento horizontal.

O <fieldset>ato é como se houvesse uma regra CSS fieldset { min-width: min-content; }. ( min-contentsignifica, grosso modo, a menor largura que não causa a transbordamento de uma criança.) Se eu substituir a <fieldset>com uma <div>pormin-width: min-content , ela parecerá exatamente a mesma. No entanto, não há regra min-contentnos meus estilos, na folha de estilo padrão do navegador ou visível no CSS Inspector do Firebug. Tentei substituir todos os estilos visíveis no <fieldset>CSS Inspector do Firebug e na folha de estilo padrão do Firefox forms.css , mas isso não ajudou. Substituindo especificamente min-widthe widthtambém não fez nada.

Código

HTML do conjunto de campos:

<fieldset>
    <div class="wrapper">
        <select id="section" name="section">
            <option value="-1"></option>
            <option value="1501" selected="selected">Sphinx of black quartz, judge my vow. The quick brown fox jumps over the lazy dog.</option>
            <option value="1480">Subcontractor</option>
            <option value="3181">Valley</option>
            <option value="3180">Ventura</option>
            <option value="3220">Very Newest Section</option>
            <option value="1481">Visitor</option>
            <option value="3200">N/A</option>
        </select>
    </div>
</fieldset>

Meu CSS que deveria estar funcionando, mas não é:

fieldset {
    /* hide fieldset-specific visual features: */
    margin: 0;
    padding: 0;
    border: none;
}

select {
    max-width: 100%;
}

Redefinir as widthpropriedades para os padrões não faz nada:

fieldset {
    width: auto;
    min-width: 0;
    max-width: none;
}

CSS adicional no qual tento e não consigo corrigir o problema :

/* try lots of things to fix the width, with no success: */
fieldset {
    display: block;
    min-width: 0;
    max-width: 100%;
    width: 100%;
    text-overflow: clip;
}

div.wrapper {
    width: 100%;
}

select {
    overflow: hidden;
}

Mais detalhes

O problema também ocorre neste exemplo mais abrangente e complicado do jsFiddle , que é mais semelhante à página da Web que estou tentando corrigir. Você pode ver que isso <select>não é o problema - um bloco embutido divtambém falha ao redimensionar. Embora este exemplo seja mais complicado, suponho que a correção para o caso simples acima também conserte esse caso mais complicado.

[Editar: veja os detalhes de suporte do navegador abaixo.]

Uma coisa curiosa sobre esse problema é que, se você definirdiv.wrapper { width: 50%; } , as <fieldset>paradas <select>serão redimensionadas no ponto e o tamanho completo atingirá a borda da viewport. O redimensionamento acontece como se <select>tivesse width: 100%, mesmo que <select>pareça width: 50%.

após redimensionar com div de wrapper de 50% de largura

Se você dar a <select>si mesmowidth: 50% , que o comportamento não ocorre; a largura é simplesmente definida corretamente.

após redimensionar com seleção de 50% de largura

Eu não entendo o motivo dessa diferença. Mas isso pode não ser relevante.

Eu também achei a pergunta muito semelhante HTML fieldset permite que as crianças se expandam indefinidamente . O solicitante não conseguiu encontrar uma solução e acha que não há solução além de remover o <fieldset>. Mas eu estou pensando, se é realmente impossível corrigir a <fieldset>tela, por que isso? O que, em <fieldset>'s especificação ou padrão CSS ( como desta questão ) faz com que este comportamento? Esse comportamento especial provavelmente está documentado em algum lugar, pois vários navegadores funcionam assim.

Objetivo e requisitos em segundo plano

O motivo pelo qual estou tentando fazer isso é como parte da criação de estilos para dispositivos móveis em uma página existente em formato grande. O formulário possui várias seções, e uma parte dele está envolvida em um <fieldset>. Em um smartphone (ou se você reduzir a janela do navegador), a parte da página com <fieldset>é muito maior que o restante do formulário. A maior parte do formulário restringe sua largura, mas a seção com <fieldset>não, forçando o usuário a diminuir o zoom ou rolar para a direita para ver toda a seção.

Tenho o cuidado de simplesmente remover o <fieldset>, pois ele é gerado em muitas páginas em um aplicativo grande, e não tenho certeza de quais seletores em CSS ou JavaScript podem depender dele.

Eu posso usar JavaScript se precisar, e uma solução JavaScript é melhor que nada. Mas se o JavaScript é a única maneira de fazer isso, ficaria curioso para ouvir uma explicação sobre por que isso não é possível usando apenas CSS e HTML.


Editar: suporte ao navegador

No site, preciso oferecer suporte ao Internet Explorer 8 e posterior (acabamos de deixar o suporte para o IE7), o Firefox mais recente e o Chrome mais recente. Esta página em particular também deve funcionar em smartphones iOS e Android. O comportamento levemente degradado, mas ainda utilizável, é aceitável para o Internet Explorer 8.

Testei novamente meu fieldsetexemplo quebrado em diferentes navegadores. Na verdade, ele já funciona nesses navegadores:

  • Internet Explorer 8, 9 e 10
  • cromada
  • Chrome para Android

Ele quebra nesses navegadores:

  • Raposa de fogo
  • Firefox para Android
  • Internet Explorer 7

Assim, o único navegador que me interessa é o Firefox (no computador e no celular). Se o código fosse corrigido e funcionasse no Firefox sem quebrá-lo em outros navegadores, isso resolveria o meu problema.

O modelo HTML do site usa comentários condicionais do Internet Explorer para adicionar classes como .ie8e .oldieao <html>elemento. Você pode usar essas classes em seu CSS se precisar solucionar as diferenças de estilo no IE. As classes adicionadas são as mesmas da versão antiga do HTML5 Boilerplate .


41
parabéns a este excelente artigo
Alp

Seu exemplo simples: forneça <fieldset>(ou div.wrapper) a largura que for necessária e select { width:100% }. max-widthparece fornecer ao elemento uma parte da largura original de seu pai , depois não é dimensionado, enquanto que widthé dimensionado com seu pai. Eu acho que vai fazer o que você quer (mas eu poderia ter entendido mal). No seu violino mais complexo, tente dar aos campos da coluna esquerda uma largura de% e uma largura de pixel mínima. Em seguida, forneça os campos à direita 100 - (campos da esquerda -% - largura)% de largura.
Trojan

Acabei de ter outro pensamento: e se você definir a largura mínima do fieldset como 0? Isso por si só provavelmente não resolverá o problema, mas possivelmente vale a pena tentar resolver. Eu estou trabalhando por um caminho diferente agora, mas se isso não funcionar eu vou tentar isso também
Trojan

Você precisa do rótulo e do campo para permanecer na mesma linha? Para pequenas viewports, elas se sobrepõem. Por que não torná-lo um pouco responsivo e mudar para uma nova linha, se necessário?
Trojan

Respostas:


346

Atualização (25 de setembro de 2017)

O bug do Firefox descrito abaixo foi corrigido no Firefox 53 e o link para esta resposta foi finalmente removido da documentação do Bootstrap .

Além disso, minhas sinceras desculpas aos colaboradores da Mozilla que tiveram que bloquear a remoção do suporte para -moz-document parte devido a esta resposta.

O conserto

No WebKit e Firefox 53+, você acabou de definir min-width: 0;no fieldset para substituir o valor padrão demin-content

Ainda assim, o Firefox é um pouco ... estranho quando se trata de conjuntos de campos. Para fazer isso funcionar em versões anteriores, você deve alterar a displaypropriedade do conjunto de campos para um dos seguintes valores:

  • table-cell (recomendado)
  • table-column
  • table-column-group
  • table-footer-group
  • table-header-group
  • table-row
  • table-row-group

Destes, eu recomendotable-cell . Ambos table-rowe table-row-groupimpedi-lo de mudar de largura, enquanto que table-columnetable-column-group impedir a alteração de altura.

Isso (um tanto razoavelmente) interromperá a renderização no IE. Como apenas o Gecko precisa disso, é possível usar justificadamente @-moz-document- uma das extensões CSS proprietárias da Mozilla - para ocultá-lo de outros navegadores:

@-moz-document url-prefix() {
    fieldset {
        display: table-cell;
    }
}

(Aqui está uma demonstração do jsFiddle .)


Isso conserta as coisas, mas se você é como eu, sua reação foi algo como ...

O que.

Não é uma razão, mas não é bonito.

A apresentação padrão do elemento fieldset é absurda e essencialmente impossível de especificar em CSS. Pense bem: a borda do fieldset desaparece onde se sobrepõe a um elemento de legenda, mas o fundo permanece visível! Não há como reproduzir isso com qualquer outra combinação de elementos.

Para completar, as implementações estão cheias de concessões ao comportamento herdado. Uma delas é que a largura mínima de um conjunto de campos nunca é menor que a largura intrínseca de seu conteúdo. O WebKit oferece uma maneira de substituir esse comportamento, especificando-o na folha de estilo padrão, mas o Gecko² vai além e o impõe no mecanismo de renderização .

No entanto, os elementos internos da tabela constituem um tipo de quadro especial no Gecko. Restrições dimensionais para elementos com esses displayvalores definidos são calculadas em um caminho de código separado , contornando completamente a largura mínima imposta imposta aos conjuntos de campos.

Novamente - o bug para isso foi corrigido no Firefox 53, então você não precisa desse hack se estiver apenas visando versões mais recentes.

O uso é @-moz-documentseguro?

Para esta questão, sim. @-moz-documentfunciona como planejado em todas as versões do Firefox até 53, onde esse bug foi corrigido.

Isso não é acidente. Em parte devido a esta resposta, o bug para limitar @-moz-documentas folhas de estilo do usuário / UA ficou dependente do bug do fieldset subjacente que foi corrigido primeiro.

Além disso, não use @-moz-documento Firefox como alvo no seu CSS , apesar de outros recursos.³


¹ O valor pode ser prefixado. Segundo um leitor, isso não tem efeito no Android 4.1.2 Stock Browser e possivelmente em outras versões antigas; Não tive tempo de verificar isso.

² Todos os links para a fonte Gecko nesta resposta se referem ao 5065fdc12408 changeset , confirmado em 29 de julho de 2013; você pode comparar as notas com a revisão mais recente do Mozilla Central .

³ Veja, por exemplo, SO # 953491: segmentando apenas o Firefox com CSS e truques CSS: hacks CSS direcionados ao Firefox para artigos amplamente referenciados em sites de alto perfil.


5
Acabei de perceber que a correção foi interrompida no IE, apenas para vir aqui e descobrir que você já editou a solução para isso. Obrigado! A solução Gecko hack funciona bem para mim em cada navegador.
Rory O'Kane

Estava arrancando meu cabelo com esse problema, mas sua correção é perfeita - exceto que parece funcionar apenas no Firefox. Alguma sugestão para outros navegadores, especialmente navegadores móveis? O meu maior problema é o redimensionamento devido à mudança de orientação em dispositivos móveis ...
Adriaan Nel

30
Esta é uma resposta absolutamente excelente - completa, pesquisada e concisa. Obrigado.
Iamkeir

16
Claro que é uma resposta absolutamente excelente! A documentação oficial do Bootstrap aponta aqui
Ranhiru Jude Cooray /

1
Bem, eu nunca soube disso sobre conjuntos de campos. Eu aprendi algo aqui hoje.
superluminary

11

Problema no Safari no iOS com resposta selecionada

Achei a resposta de Jordan Gray particularmente útil. No entanto, não pareceu resolver esse problema no Safari iOS para mim.

O problema para mim é simplesmente que o fieldset não pode ter uma largura automática se o elemento tiver uma largura máxima como% de largura.

Correção para problema

Simplesmente definir o fieldset para ter uma largura de 100% de seu contêiner parece contornar esse problema.

Exemplo

fieldset {
    min-width: 0; 
    width: 100%; 
}

Consulte o exemplo abaixo para exemplos de trabalho - se você remover a largura% do conjunto de campos ou substituí-lo por automático, ele não continuará funcionando.

JSFiddle | Codepen


1
Este é um ótimo complemento para o problema geral, não pensei em testá-lo no iOS. :) Eu quase acho que isso pode valer a pena você perguntar e responder como uma nova pergunta também. Vou tentar fazer alguns testes extras esta semana e vincular a esta resposta, se funcionar.
Jordan Grey

3

Eu lutei por muitas horas com isso e, basicamente, o navegador está aplicando um estilo computado que você precisa substituir no seu CSS. Eu esqueço a propriedade exata que está sendo definida nos fieldsetelementos versus divs (talvez min-width?).

Meu melhor conselho seria alterar seu elemento para a div, copiar os estilos computados do seu inspetor e, em seguida, alterar seu elemento novamente fieldsete comparar os estilos computados para encontrar o culpado.

Espero que ajude.

Atualização: a adição de display: table-cellajuda em navegadores não Chrome.


Comparei cada propriedade CSS do fieldsete divsobre esta página no Firebug. Isso não ajudou. No Firebug, as únicas propriedades com valores diferentes eram widthe perspective-origin. O widthfoi numericamente diferentes, mas os fieldset's widthera auto, como os div' s. E o perspective-originé apenas uma função dos width- 50% dele por padrão.
Rory O'Kane

No entanto, a comparação ajudou de certa forma no Chrome Web Inspector. Descobri logo após abrir o meu exemplo que ele está funcionando no Chrome! Eu adicionei o min-width: 0;meu exemplo depois de testar no Chrome, mas parece que isso resolveu o problema no Chrome. O Web Inspector me diz que o Chrome tem o estilo min-width: -webkit-min-content;, como eu imaginei. Então agora só preciso resolver o problema no Firefox e possivelmente em outros navegadores em que ainda não testei.
Rory O'Kane

Ainda bem que ajudou um pouco. Consegui resolver meu problema em outros navegadores com "display: table-cell". Não acho que essa não seja a melhor solução, mas espero que funcione para você.
Phdj

2

.fake-select { white-space:nowrap; }fez com que o fieldset interpretasse o .fake-selectelemento pela largura original, e não pela largura forçada (mesmo quando o estouro está oculto).

Retirar essa regra, e mudança .fake-selecté max-width:100%para apenas width:100%e fits tudo. A ressalva é que você vê todo o conteúdo do falso-select, mas não acho que isso seja tão ruim e se encaixa horizontalmente agora.

Atualização: com as regras atuais no violino a seguir (que contém apenas seleções reais), os filhos do fieldset são restritos a corrigir larguras. Além de remover regras .fake-selecte corrigir comentários (de // commentpara /* comment */, observei alterações no CSS do violino.

Compreendo melhor o seu problema agora, e o violino reflete algum progresso. Eu defino regras padrão para todos os se <select>reservo .xxlargepara aqueles que você sabe que terão mais de 480px (e isso só funciona porque você conhece a largura de #viewport, e pode adicionar manualmente a classe àqueles muito grandes. Requer apenas um pouco de teste )

Prova


Qualquer que seja a correção que você use, precisa funcionar de maneira real <select>. O site atual possui apenas <select>s. O objetivo fake-selectera ter as regras de layout de a <select>sem realmente ser a <select>, apenas para mostrar que esse comportamento não é um bug do navegador que acontece apenas com <select>elementos. Então, mudar os estilos de .fake-selectser menos parecido com um <select>derrota o objetivo.
Rory O'Kane

Eu substituí o .fake-select caixa por uma <select>(idêntica à que já está presente) para demonstrar. Os elementos estão todos restritos à largura do pai (exceto quando você clica nele, suspensa as opções, que são exibidas em uma única linha - mas acho que você não pode controlar isso). Também removi todas as regras para .fake-select. O violino atual faz o que você precisa?
Trojan

Isso não. width: 100%funciona com os menus longos da página, mas não funciona corretamente com menus curtos. Ele expande menus curtos para toda a largura da página, mas eu quero que menus curtos mantenham sua largura curta. Os menus devem ter a largura natural, se houver espaço, mas 100% de largura, se forem grandes demais para os pais. Isso é o que max-widthdeveria fazer, mas não o faz neste caso.
Rory O'Kane

Fiz mais algumas alterações, separando "all <select>s" de "long <select>s" e agora trabalhando apenas na largura do plano de fundo.
Trojan

#viewporttambém não possui uma largura fixa. É por isso que eu coloquei o botão Redimensionar viewport na página - para que você possa testar se tudo funciona, independentemente da largura da viewport. Assim como.fake-select é um substituto para um real <select>para testes, #viewporté um substituto para uma viewport real. (Uma "janela de visualização" é basicamente uma janela do navegador). Incluí #viewportna página para que você pudesse ver facilmente os elementos que ficam fora da janela de visualização, em vez de precisar rolar para vê-los.
Rory O'Kane
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.