30 votes

Faire en sorte que le dernier élément prenne la largeur restante avec habillage (et avec le support IE9)

Je suis à la recherche d'un moyen d'aligner plusieurs éléments les uns à côté des autres, en les faisant envelopper une fois qu'ils sont remplis de la ligne, et le dernier point de prendre la largeur restante de la dernière ligne.

J'ai trouvé plusieurs questions sur un sujet similaire avant, avec des solutions faisant généralement de l'utilisation par les éléments d' float: left pour les aligner sur une ligne, et overflow: hidden sur le dernier élément qui prend de l'espace restant automatiquement. Ces solutions fonctionnent bien dans une seule ligne, mais ils s'arrêtent de travailler une fois il y a suffisamment d'articles avant le dernier élément, qu'ils l'envelopper dans plusieurs lignes. Ensuite, le "dernier" élément est toujours rendu dans la première ligne (si il y a assez d'espace), ce qui n'est plus le dernier élément.

Cependant, je veux que le dernier élément de rester le dernier élément à tout moment, pour l'avoir dans la dernière ligne-quelle que soit la ligne qui est-et de prendre automatiquement le reste de l'espace.

C'est assez simple, avec un emballage flexbox, car vous avez juste besoin de mettre flex: 0 auto sur les premiers éléments de leur faire prendre tout l'espace dont ils ont besoin (sans prendre de plus), et flex: 1 sur le dernier élément à prendre il prendre le reste. Cependant, j'ai besoin de prendre en charge Internet Explorer 9, flexbox est malheureusement hors de question.

C'est la façon dont la situation ressemble. Lors de l'exécution du fragment de code, vous pouvez utiliser le bouton "Basculer flex zone" bouton pour basculer flexbox mode qui montre la façon dont il devrait ressembler.

* { box-sizing: border-box; }
.container {
  width: 300px;
  background: snow;
  padding: 5px;
  overflow: auto;
}
.element {
  float: left;
  margin: 2px 5px 2px 0;
  background: lavender;
}
.last {
  overflow: hidden;
}
.last > input {
  width: 100%;
}

/* Working solution with flex box */
.flex .container {
  display: flex;
  flex-wrap: wrap;
}
.flex .element {
  flex: 0 auto;
}
.flex .last {
  flex: 1;
}
<div class="container">
  <div class="element">Foo</div>
  <div class="element">Foo bar</div>
  <div class="element">Foo bar baz</div>

  <div class="last"><input type="text" /></div>
</div>

<div class="container">
  <div class="element">Foo</div>
  <div class="element">Foo bar</div>
  <div class="element">Foo bar baz</div>
  <div class="element">Foo</div>
  <div class="element">Foo bar</div>
  <div class="element">Foo bar baz</div>

  <div class="last"><input type="text" /></div>
</div>

<button onclick="this.parentNode.classList.toggle('flex')">Toggle flex box</button>

13voto

CodeiSir Points 7265

Voici la solution:

  • Ajouter un <div style="clear:left;margin-top:22px"></div> avant l' .last élément*
  • Ajouter margin-top: -22px; de .last lorsque le montant est environ la même que la hauteur de la ligne
  • Si vous ne voulez pas il trop petit add min-width de .last et qu'il fonctionne comme vous le souhaitez
    Aussi min-width: 1px; est requise dans la classe pour éviter de tomber à 0, dans des cas particuliers.

Testé et de travail dans IE8+, Edge, Chrome, Opera, Firefox

* { box-sizing: border-box; }
.container {
  width: 300px;
  background: snow;
  padding: 5px;
  overflow: auto;
}
.element {
  float: left;
  margin: 2px 5px 2px 0;
  background: lavender;
}
.last {
  overflow: hidden;
  margin-top: -22px;
  min-width: 1px;
}
.last > input {
  width: 100%;
}
.container .unwrap {
  clear: left;
  margin-top: 22px
}
<div class="container">
  <div class="unwrap"></div>
  <div class="last"><input type="text" /></div>
</div>

<div class="container">
  <div class="element">Foo</div>
  <div class="element">Foo bar</div>
  <div class="element">Foo bar baz</div>
  <div class="unwrap"></div>
  <div class="last"><input type="text" /></div>
</div>

<div class="container">
  <div class="element">Foo</div>
  <div class="element">Foo bar</div>
  <div class="element">Foo bar baz boo</div>
  <div class="unwrap"></div>
  <div class="last" style="min-width: 100px">
    <input type="text" placeholder="min-width 100px" />
  </div>
</div>

<div class="container">
  <div class="element">Foo</div>
  <div class="element">Foo bar</div>
  <div class="element">Foo bar baz</div>
  <div class="element">Foo</div>
  <div class="element">Foo bar</div>
  <div class="element">Foo bar baz</div>
  <div class="unwrap"></div>
  <div class="last"><input type="text" /></div>
</div>

<div class="container">
  <div class="element">Foo</div>
  <div class="element">Foo bar</div>
  <div class="element">Foo bar baz</div>
  <div class="element">Foo baaaaaaaaaaaaaaaaaaaaaaar</div>
  <div class="unwrap"></div>
  <div class="last"><input type="text" /></div>
</div>

<div class="container">
  <div class="element">Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz</div>
  <div class="unwrap"></div>
  <div class="last"><input type="text" /></div>
</div>

* margin-top:22px seulement pour éviter l'entrée de glisser dans le cas où il n'y a pas d'éléments dans le conteneur. Il devrait être la valeur absolue de la marge négative de l'entrée

4voto

Pangloss Points 19560

La solution suivante n'est pas parfait, c'est à l'aide de la position des hacks. Si vous désactivez overflow: hidden; vous verrez chaque <input> fait a la même largeur que le conteneur. Mais avec un peu de CSS réglages visuels, il semble bon et peut travailler sur ok.

Question 1: si vous tapez plus de caractères qu'il peut visuellement ajustement, le point de vue se décale vers la gauche.

Solution 1: définir un maxlength de la valeur à l' <input> pourrait aider.

jsfiddle

* {
  box-sizing: border-box;
}
.container {
  width: 300px;
  background: snow;
  padding: 5px;
  position: relative;
  overflow: hidden; /*hide the overflow*/
}
span:after {
  content: "\00A0" /*just for one no-break space*/
}
input {
  width: 100%;
  position: absolute; /*without any top/right/bottom/left value*/
  border: 2px solid grey;
  border-width: 0 0 2px 0;
}
input:focus {
  outline: 0;
}
<div class="container">
  <span>FooFoo barFoo bar baz</span>
  <input type="text" />
</div>

<div class="container">
  <span>FooFoo barFoo bar bazFooFoo barFoo bar baz bla</span>
  <input type="text" />
</div>

1voto

LGSon Points 1306

Et pour tout le monde, qui serait comme une des options de script pour travailler avec, ici, c'est pour vous aussi.

Juste ajouter data-calcattr pour les éléments que vous souhaitez avoir son width propriété a la valeur width: calc(100% - ??px);??px est sa largeur.

Note de côté:

Le script aurait probablement besoin d'ajustements à faire pour les futures frontières, marges, etc., donc il sert plus comme une façon de le faire.

function calcattr() {
  var els = document.querySelectorAll('[data-calcattr]');
  // TODO: add switch to enable calc. different properties like
  //       get the remaining height as well, by checking the 
  //       data-calcattr value, i.e.: data-calcattr='height'
  for (i = 0; i < els.length; i++) {
    els[i].setAttribute("style", "width: 0");    
    var lpos = parseInt(els[i].getBoundingClientRect().left);
    var minw = parseFloat(getComputedStyle(els[i]).getPropertyValue('min-width'));
    var calcwidth = "calc(100% - " + (lpos + 2) + "px)";
    els[i].setAttribute("style", "width: " + calcwidth);
    if ((els[i].getBoundingClientRect().right - lpos) < minw) {
      els[i].setAttribute("style", "width: 100%");
    }
  }
}

window.onload = calcattr;

(function() {
  window.addEventListener("resize", resizeThrottler, false);
  var resizeTimeout;
  function resizeThrottler() {
    if ( !resizeTimeout ) {
      resizeTimeout = setTimeout(function() {
        resizeTimeout = null;
        actualResizeHandler();
      }, 66);
    }
  }
  function actualResizeHandler() {
    calcattr();
  }
}());
* { box-sizing: border-box; }
.container {
  width: 300px; //70%;
  background: snow;
  padding: 5px;
  overflow: auto;
}
.fullwidth {
  width: 100%;
}
.element {
  float: left;
  margin: 2px 5px 2px 0;
  background: lavender;
}
.last > input {
  width: 100%;
}
.last {
  float: left;
  min-width: 20px;
}
<div class="container">
  <div class="element">Foo</div>
  <div class="element">Foo bar</div>
  <div class="element">Foo bar baz</div>

  <div class="last" data-calcattr><input type="text" /></div>
</div>

<div class="container">
  <div class="element">Foo</div>
  <div class="element">Foo bar</div>
  <div class="element">Foo bar baz</div>
  <div class="element">Foo</div>
  <div class="element">Foo bar</div>
  <div class="element">Foo bar baz</div>
  <div class="element">Foo</div>
  <div class="element">Foo bar</div>
  <div class="element">Foo bar baz</div>

  <div class="last" data-calcattr><input type="text" /></div>
</div>

<div class="container fullwidth">
  <div class="element">Foo</div>
  <div class="element">Foo bar</div>
  <div class="element">Foo bar baz</div>
  <div class="element">Foo</div>
  <div class="element">Foo bar</div>
  <div class="element">Foo bar baz</div>
  <div class="element">Foo</div>
  <div class="element">Foo bar</div>
  <div class="element">Foo bar baz</div>
  <div class="element">Foo</div>
  <div class="element">Foo bar</div>
  <div class="element">Foo bar baz</div>
  <div class="element">Foo</div>
  <div class="element">Foo bar</div>
  <div class="element">Foo bar baz</div>

  <div class="last" data-calcattr><input type="text" /></div>
</div>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X