J'ai un <ul>
qui est un flex-box et un tas de <li>
s qui sont les flex-items.
J'essaie d'obtenir le <li>
pour avoir une largeur flexible, qui reste entre deux tailles en utilisant min-width et max-width. Cela fonctionne très bien tant qu'ils sont sur la même ligne. Cependant, lorsqu’ils sont bouclés, les <li>
s de la nouvelle ligne utilisent autant d’espace que possible. Ce qui signifie qu'ils sont petits sur la première ligne et gros sur la deuxième ligne quand ils sont peu nombreux.
Existe-t-il un moyen de demander à flexbox de conserver la largeur des éléments après l’emballage, tout en conservant la largeur de celui-ci?
démo d'emballage:
Mon code ressemble à ceci:
<ul>
<li>
<figure>
<img src="http://placekitten.com/g/250/250">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/100/100">
</figure>
</li>
<!-- ... -->
</ul>
Et le CSS:
ul {
display: flex;
flex-wrap: wrap;
}
li {
min-width: 40px;
max-width: 100px;
flex: 1 0 0;
}
Voici un exemple en direct sur codepen avec quelques commentaires supplémentaires, redimensionnez votre fenêtre pour la voir se dérouler.
Ce n'est pas quelque chose que j'appellerais une solution} _, mais une solution de contournement plutôt élégante qui utilise uniquement des requêtes multimédia, et plus important encore sans JavaScript!
@mixin flex-wrap-fix($flex-basis, $max-viewport-width: 2000px) {
flex-grow: 1;
flex-basis: $flex-basis;
max-width: 100%;
$multiplier: 1;
$current-width: 0px;
@while $current-width < $max-viewport-width {
$current-width: $current-width + $flex-basis;
$multiplier: $multiplier + 1;
@media(min-width: $flex-basis * $multiplier) {
max-width: percentage(1/$multiplier);
}
}
}
Appliquez le mixin à votre article flex:
.flex-item {
@include flex-wrap-fix(100px)
}
Le mélange ci-dessus devrait faire l'affaire, à condition que votre largeur de conteneur flex corresponde à la taille de votre fenêtre, comme c'est le cas dans l'exemple d'OP. Les requêtes multimédias ne vous aideront pas, car elles sont toujours basées sur la largeur de la fenêtre. Toutefois, vous pouvez utiliser la bibliothèque css-element-queries
et ses requêtes d’éléments au lieu des requêtes multimédias du navigateur. Voici un mix que vous pouvez appliquer au flex conteneur:
@mixin flex-container-wrap-items($flex-basis, $max-expected-width: 2000px) {
display: flex;
flex-wrap: wrap;
> * {
max-width: 100%;
flex-grow: 1;
flex-basis: $flex-basis;
}
$multiplier: 1;
$current-width: 0px;
@while $current-width < $max-expected-width {
$current-width: $current-width + $flex-basis;
$multiplier: $multiplier + 1;
&[min-width~="#{$flex-basis * $multiplier}"] > * {
max-width: percentage(1/$multiplier);
}
}
}
Supposons, comme dans l'exemple du PO, que nous voulions que chaque élément ait une largeur maximale de 100px
. Nous savons donc que pour une largeur de navigateur de 100px
, nous pouvons adapter un élément par ligne, et ainsi de suite:
| Viewport Width | Max Item Count Per Row | Item Width (min-max) |
|----------------|------------------------|----------------------|
| <= 100 | 1 | 0px - 100px |
| <= 200 | 2 | 50px - 100px |
| <= 300 | 3 | 50px - 100px |
| <= 400 | 4 | 50px - 100px |
| <= 500 | 5 | 50px - 100px |
| <= 600 | 6 | 50px - 100px |
Nous pouvons écrire des requêtes multimédia pour créer les règles suivantes:
| Viewport Width | Max Item Count Per Row | Item Max Width | Calculation |
|------------------------------------------------------------------------|
| <= 100px | 1 | 100% | (100/1) |
| <= 200px | 2 | 50% | (100/2) |
| <= 300px | 3 | 33.33333% | (100/3) |
| <= 400px | 4 | 25% | (100/4) |
| <= 500px | 5 | 20% | (100/5) |
| <= 600px | 6 | 16.66666% | (100/6) |
Comme ça:
li {
flex: 1 0 0
max-width: 100%;
}
@media(min-width: 200px) {
li { max-width: 50%; }
}
@media(min-width: 300px) {
li { max-width: 33.33333%; }
}
@media(min-width: 400px) {
li { max-width: 25%; }
}
@media(min-width: 500px) {
li { max-width: 20%; }
}
@media(min-width: 600px) {
li { max-width: 16.66666%; }
}
Bien sûr, c'est répétitif, mais vous utilisez probablement une sorte de pré-processeur, qui peut prendre en charge la répétition pour vous. C’est précisément ce que fait le mixin de la section TL; DR ci-dessus.
Il ne nous reste plus qu'à spécifier 100px
en tant que flex-basis
et éventuellement la largeur maximale de la fenêtre du navigateur (définie par défaut sur 2000px
) pour créer les requêtes multimédia pour:
@include flex-wrap-fix(100px)
Enfin, une version "forkée" de l'exemple CodePen d'origine avec la sortie souhaitée, utilisant le mix ci-dessus:
J'ai essayé avec votre codepen et j'ai mis flex: 0 1 10%
Bien sûr, vous pouvez définir la base flexible comme vous le souhaitez. Je voulais simplement prouver que si vous définissez la base flexible et que vous la permettez de la réduire, elle se comportera beaucoup mieux.
Je pense que c'est ce dont vous aviez besoin. Voici l'aperçu: http://codepen.io/anon/pen/bwqNEZ
À votre santé
Je pense que je l'ai eu ... mais c'est hacky. Le résultat est 14 images, chacune allant de 100 pixels de large à 40 pixels, même sur plusieurs lignes.
<li>
s d'origine et ajout de ceux-ci au flex <ul>
. Ensuite, le deuxième ensemble a été rendu invisible:
li:nth-of-type(n + 15) {
visibility: hidden;
}
Afin de maintenir une flexibilité uniforme, les modifications suivantes ont été apportées à chaque <li>
:
li {
min-width: 40px;
max-width: 10%;
flex: 1 0 100px;
}
S'il vous plaît examiner le CodePen
et/ou Snippet en mode Full Page.
ul {
display: flex;
flex-wrap: wrap;
max-height: 258px;
}
li {
min-width: 40px;
max-width: 10%;
flex: 1 0 100px;
}
ul,
li {
margin: 0;
padding: 0;
list-style: none;
}
ul {
background-color: tomato;
}
li {
margin: 0.5em;
background-color: darkgreen;
}
li img {
width: 100%;
opacity: 0.5;
}
li figure,
li img {
margin: 0;
padding: 0;
}
li:nth-of-type(n + 15) {
visibility: hidden;
}
<ul>
<li>
<figure>
<img src="http://placekitten.com/g/250/250">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/101/101">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/201/201">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/150/150">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/80/80">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/111/111">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/40/40">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/110/110">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/75/75">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/89/89">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/150/150">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/32/32">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/61/61">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/320/320">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/250/250">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/101/101">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/201/201">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/150/150">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/80/80">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/111/111">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/40/40">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/110/110">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/75/75">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/89/89">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/150/150">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/32/32">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/61/61">
</figure>
</li>
<li>
<figure>
<img src="http://placekitten.com/g/320/320">
</figure>
</li>
</ul>
La définition des pourcentages min-width
et max-width
a permis à toutes les images de conserver la même largeur lors de leur insertion sur la ligne suivante. Ce n'est pas idéal, mais plus proche de ce que vous recherchez?
li {
min-width: 15%;
max-width: 15%;
}
Cela ne fonctionne pas très bien, mais vous pouvez réaliser quelque chose dans cette direction avec des colonnes.
column-gap: 10px;
column-width: 150px;
Pour Stylus, vous pouvez utiliser ce mixin: https://codepen.io/anon/pen/Epjwjq
flex-wrap-fix($basis, $max) {
flex-grow: 1
flex-basis: $basis
max-width: 100%
$multiplier = ceil($max / $basis)
for i in (1..$multiplier) {
@media(min-width: ($basis * i)) {
max-width: percentage(1/i)
}
}
}
Ma solution n’est pas idéale car elle s’appuie sur JQuery: http://codepen.io/BigWillie/pen/WwyEXX
CSS
ul {
display: flex;
flex-wrap: wrap;
}
li {
min-width: 40px;
max-width: 100px;
flex: 1;
}
JavaScript
var eqRowFlexItem = function(elem) {
var w;
var $elem = $(elem);
// Clear out max-width on elements
$elem.css('max-width', '');
w = $(elem).eq(0).width();
$(elem).css('max-width', w);
}
eqRowFlexItem('li');
$(window).resize(function() {
eqRowFlexItem('li');
});
Je ne suis pas tout à fait sûr si cela répond au problème. J'ai trouvé ce post, car le titre correspondait au problème que j'avais. Je recherchais un effet selon lequel j'aurais un plus grand nombre d'éléments par ligne sur des écrans plus grands - et moins d'éléments par ligne sur des écrans plus petits. Dans les deux cas, ces éléments devaient également évoluer pour s'adapter ... à tous les périphériques.
Cependant, ces éléments parasites sur la dernière ligne se développeraient toujours pour remplir l'espace restant.
JQuery obtient la largeur du premier élément - et l'applique comme largeur maximale à chaque élément. Le PO souhaitait que les blocs tombent dans une rage min-width/max-width. Définir la largeur maximale en CSS semble fonctionner. Nous effaçons l'élément max-width de la largeur, il sera donc défini par défaut sur max-width dans le fichier CSS ... puis obtiendra la largeur réelle.
J'ai eu le même problème, alors j'ai utilisé un très petit morceau de Jquery pour contrôler la largeur des boîtes et les rendre toutes identiques, même une fois qu'elles se sont déroulées.
Ma démo est sur CodePen Flex wrap, avec la même largeur sur la nouvelle ligne
function resize(){
var colWidth;
var screen = $(window).width();
if(screen < 576){
colWidth = Math.round(screen / 2) - 31;
$(".item").width(colWidth);
}
if(screen > 575 && screen < 768){
colWidth = Math.round(screen / 3) - 31;
$(".item").width(colWidth);
}
else if (screen > 767 && screen < 992){
colWidth = Math.round(screen / 4) -31;
$(".item").width(colWidth);
}
else if (screen > 991 ){
colWidth = Math.round(screen / 6) -31;
$(".item").width(colWidth);
}
}
window.onresize = function() {
resize();
}
resize();
html,
body{
padding:0;
margin:0;
}
.flex-container {
padding: 0;
margin: 0;
list-style: none;
-ms-box-orient: horizontal;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -moz-flex;
display: -webkit-flex;
display: flex;
justify-content: left;
background-color:#ddd;
}
.wrap {
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
}
.item {
background: tomato;
height: 100px;
margin:0 15px;
line-height: 100px;
color: white;
font-weight: bold;
font-size: 2em;
text-align: center;
margin-top:10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="flex-container wrap">
<li class="item">1</li>
<li class="item">2</li>
<li class="item">3</li>
<li class="item">4</li>
<li class="item">5</li>
<li class="item">6</li>
<li class="item">7</li>
<li class="item">8</li>
<li class="item">9</li>
</ul>
Ce n'est pas parfait mais vaut la peine d'essayer. http://codepen.io/anon/pen/MKmXpV
Les changements sont
li
width: 7.1428%
flex: 0 0 auto
figure
margin: 0 auto
background-color: darkgreen
min-width: 40px
max-width: 100px