73 votes

Comment fonctionne le flex-wrap avec align-self, align-items et align-content ?

align-self

Dans le code suivant, align-self travaille avec flex-wrap: nowrap .

enter image description here

flex-container {
  display: flex;
  flex-wrap: nowrap;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
flex-item:last-child {
  align-self: flex-end;
  background-color: crimson;
}

<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Mais lorsque le conteneur passe à flex-wrap: wrap le align-self ne fonctionne pas.

enter image description here

flex-container {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
flex-item:last-child {
  align-self: flex-end;
  background-color: crimson;
}

<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

align-items

De même, pourquoi align-items travailler ici (wrap désactivé) :

enter image description here

flex-container {
  display: flex;
  flex-wrap: nowrap;
  align-items: flex-end;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}

<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

...mais pas ici (wrap enabled) :

enter image description here

flex-container {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}

<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

align-content

Avec flex-wrap: nowrap le align-content ne permettra pas de centrer verticalement les éléments flex ici :

enter image description here

flex-container {
  display: flex;
  flex-wrap: nowrap;
  align-content: center;
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}

<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Mais ensuite, bizarrement, si l'enveloppement est activé et que align-content est laissé de côté, le conteneur crée ici de larges espaces entre les rangées :

enter image description here

flex-container {
  display: flex;
  flex-wrap: wrap;
  /* align-content: center; */
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}

<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Et align-self fonctionne à nouveau.

enter image description here

flex-container {
  display: flex;
  flex-wrap: wrap;
  /* align-content: center; */
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}

flex-item:nth-child(even) {
  align-self: flex-end;
  background-color: crimson;
}

<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Comment flex-wrap travailler avec align-self , align-items et align-content?

163voto

Michael_B Points 15556

Réponse courte

Bien que le flex-wrap semble assez basique - elle contrôle si les éléments flexibles peuvent être enveloppés - elle a en fait un impact important sur l'ensemble de la disposition flexbox.

Le site flex-wrap détermine le type de conteneur flexible que vous utiliserez.

  • flex-wrap: nowrap crée un conteneur flexible à ligne unique
  • flex-wrap: wrap et wrap-reverse créer un conteneur flexible multi-lignes

Le site align-items et align-self fonctionnent dans des conteneurs à une ou plusieurs lignes. Cependant, elles ne peuvent avoir d'effet que lorsqu'il y a de l'espace libre dans l'axe transversal de la ligne flexible.

Le site align-content ne fonctionne que dans les conteneurs à plusieurs lignes. Elle est ignorée dans les conteneurs à ligne unique.


Explication

Le site spécification de flexbox fournit quatre propriétés de mots-clés pour l'alignement des éléments flexibles :

  • align-items
  • align-self
  • align-content
  • justify-content

Pour comprendre les fonctions de ces propriétés, il est important de comprendre d'abord la structure d'un conteneur Flex.


Partie 1 : Comprendre l'axe principal et l'axe transversal d'un conteneur Flex

Les axes X et Y

Un conteneur flexible fonctionne dans deux directions : l'axe des x (horizontal) et l'axe des y (vertical).

x-axis and the y-axis

                                                                                                                 Source : Wikipedia

Les éléments enfants d'un conteneur flex, appelés "éléments flex", peuvent être alignés dans les deux sens.

Il s'agit de l'alignement des flexibles à son niveau le plus fondamental.

L'axe principal et l'axe transversal

Les axes x et y sont superposés, dans la mise en page flex, à l'aide des éléments suivants principal et croix axes.

Par défaut, l'axe principal est horizontal (axe des x), et l'axe transversal est vertical (axe des y). Il s'agit du paramètre initial, tel que défini par l'attribut spécification de flexbox .

flex main axis and cross axis

                                                                                                                 Source : W3C

Cependant, contrairement aux axes x et y, qui sont fixes, les axes principaux et transversaux peuvent changer de direction.

Le site flex-direction Propriété

Dans l'image ci-dessus, l'axe principal est horizontal et l'axe transversal est vertical. Comme mentionné précédemment, il s'agit du réglage initial d'un conteneur flex.

Cependant, ces directions peuvent être facilement changées avec la fonction flex-direction propriété. Cette propriété contrôle la direction de l'axe principal ; elle détermine si les éléments flexibles s'alignent verticalement ou horizontalement.

De la spécification :

5.1. Direction du flux du Flex : le flex-direction propriété

Le site flex-direction spécifie comment les éléments flexibles sont placés dans le conteneur flex, en définissant la direction de l'axe principal du conteneur flex. du conteneur flexible. Cela détermine la direction dans laquelle les éléments flexibles sont disposés à l'extérieur.

Il existe quatre valeurs pour le flex-direction propriété :

/* main axis is horizontal, cross axis is vertical */
flex-direction: row; /* default */
flex-direction: row-reverse;

/* main axis is vertical, cross axis is horizontal */    
flex-direction: column;
flex-direction: column-reverse;

L'axe transversal est toujours perpendiculaire à l'axe principal.


Partie 2 : Lignes flexibles

À l'intérieur du conteneur, les éléments flexibles existent dans une ligne, appelée "ligne flex".

Une ligne de flexion est une ligne ou une colonne, en fonction de la nature de la ligne. flex-direction .

Un conteneur peut avoir une ou plusieurs lignes, en fonction des éléments suivants flex-wrap .

Conteneur flexible à ligne unique

flex-wrap: nowrap crée un conteneur flexible à ligne unique, dans lequel les éléments flexibles sont forcés de rester sur une seule ligne (même s'ils débordent du conteneur).

a single-line flex container (one column)

L'image ci-dessus a une ligne de flexion.

flex-container {
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap; /* <-- allows single-line flex container */
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  width: 50px;
  margin: 5px;
  background-color: lightgreen;
}

<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Conteneur flexible multi-lignes

flex-wrap: wrap ou wrap-reverse établit un conteneur flex multiligne, dans lequel les éléments flex peuvent créer de nouvelles lignes.

multi-line flex container (3 columns)

L'image ci-dessus comporte trois lignes de flexion.

flex-container {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap; /* <-- allows multi-line flex container */
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  width: 50px;
  margin: 5px;
  background-color: lightgreen;
}

<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

multi-line flex container (3 rows)

L'image ci-dessus comporte trois lignes de flexion.

flex-container {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap; /* <-- allows multi-line flex container */
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}

<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Partie 3 : Propriétés d'alignement des mots-clés

Les propriétés sont attribuées aux axes principal et transversal (et non aux axes X et Y).

Alors que le flex-direction contrôle la direction dans laquelle les éléments flexibles sont disposés, il existe quatre propriétés qui contrôlent l'alignement et le positionnement. Il s'agit de :

  • align-items
  • align-self
  • align-content
  • justify-content

Chacune de ces propriétés est affectée de façon permanente à un axe.

Le site justify-content ne fonctionne que sur l'axe principal.

Les trois align-* ne fonctionnent que sur l'axe transversal.

C'est une erreur courante de supposer que ces propriétés sont fixées aux axes x et y. Par exemple, justify-content est toujours horizontal, et align-items est toujours vertical.

Cependant, lorsque flex-direction est commuté sur column l'axe principal devient l'axe des y, et justify-content fonctionne verticalement.

L'objet de ce post est l'alignement sur l'axe transversal. Pour une explication de l'alignement sur l'axe principal et de l'alignement sur l'axe transversal, veuillez vous reporter à l'article sur l'alignement transversal. justify-content propriété, voir ce billet :

Définitions

La spécification Flexbox fournit trois propriétés de mots-clés pour l'alignement sur l'axe transversal :

  • align-items
  • align-self
  • align-content

align-items / align-self

Le site align-items aligne les éléments flexibles sur l'axe transversal de la ligne de flexion. Elle s'applique aux conteneurs flex.

Le site align-self est utilisée pour remplacer align-items sur les éléments flexibles individuels. Il s'applique aux articles flexibles.

Voici la définition de la spécification :

8.3. Alignement sur l'axe transversal : le align-items et align-self propriétés

Les éléments Flex peuvent être alignés dans l'axe transversal de la ligne courante de l'élément flex, de manière similaire à justify-content mais dans la direction perpendiculaire perpendiculaire. align-items définit l'alignement par défaut de tous les éléments du éléments du conteneur flex. align-self permet de remplacer cet alignement par défaut de remplacer cet alignement par défaut pour des éléments flex individuels.

Il y a six valeurs possibles pour align-items / align-self :

  • flex-start
  • flex-end
  • center
  • baseline
  • stretch
  • auto ( align-self seulement)

(Pour une description de chaque valeur, cliquez sur le titre de la définition de la spécification ci-dessus).

La valeur initiale de align-items est stretch Les articles flexibles s'étendront sur toute la longueur disponible de l'axe transversal du conteneur.

La valeur initiale de align-self est auto ce qui signifie qu'il hérite de la valeur de align-items .

Vous trouverez ci-dessous une illustration de l'effet de chaque valeur dans un conteneur de type "row-direction".

align-items align-self values

                                                                                                                 source : W3C

align-content

Cette propriété est légèrement plus complexe que align-items et align-self .

Voici la définition de la spécification :

8.4. Emballage des Flex Lines : le align-content propriété

Le site align-content aligne les lignes d'un conteneur flexible à l'intérieur du conteneur le conteneur flexible lorsqu'il y a un espace supplémentaire dans l'axe transversal, de la même façon que justify-content aligne les éléments individuels dans l'axe l'axe principal. Remarque : cette propriété n'a aucun effet sur un conteneur flex à ligne unique. d'une seule ligne.

Contrairement à align-items et align-self qui déplacent des objets flexibles dans leur ligne , align-content déplace les lignes flexibles dans le conteneur .

Il y a six valeurs possibles pour align-content :

  • flex-start
  • flex-end
  • center
  • space-between
  • space-around
  • stretch

(Pour une description de chaque valeur, cliquez sur le titre de la définition de la spécification ci-dessus).

Vous trouverez ci-dessous une illustration de l'effet de chaque valeur dans un conteneur de type "row-direction".

enter image description here

                                                                                                                 source : W3C

Pourquoi est-ce que align-content ne fonctionne que dans les conteneurs flexibles à plusieurs lignes ?

Dans un conteneur souple à ligne unique, la dimension transversale de la ligne est égale à la dimension transversale du conteneur. Cela signifie qu'il n'y a pas d'espace libre entre la ligne et le conteneur. Il en résulte que align-content ne peut avoir aucun effet.

Voici le section pertinente de la spécification :

Seuls les conteneurs flexibles à plusieurs lignes disposent d'un espace libre dans l'axe transversal pour l'alignement des lignes, car dans un conteneur flex à une ligne, la seule ligne s'étire automatiquement pour remplir l'espace.


Partie 4 : Des exemples expliqués

enter image description here

Dans l'exemple n°1, align-self travaille avec flex-wrap: nowrap parce que les éléments flexibles existent dans un conteneur à ligne unique. Par conséquent, il n'y a qu'une seule ligne de flexion et elle correspond à la hauteur du conteneur.

flex-container {
  display: flex;
  flex-wrap: nowrap;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
flex-item:last-child {
  align-self: flex-end;
  background-color: crimson;
}

<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

enter image description here

Dans l'exemple n°2, align-self échoue parce qu'il existe dans un conteneur à plusieurs lignes ( flex-wrap: wrap ) et align-content est réglé sur flex-start . Cela signifie que les lignes de flexion sont serrées au début de l'axe transversal, ne laissant pas d'espace libre pour les lignes de flexion. align-self pour travailler.

flex-container {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
flex-item:last-child {
  align-self: flex-end;
  background-color: crimson;
}

<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

enter image description here

L'explication de l'exemple n° 3 est la même que celle de l'exemple n° 1.

flex-container {
  display: flex;
  flex-wrap: nowrap;
  align-items: flex-end;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}

<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

enter image description here

L'explication de l'exemple n° 4 est la même que celle de l'exemple n° 2.

flex-container {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}

<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

enter image description here

L'exemple n° 5 est un conteneur à une seule ligne. En tant que tel, la dimension transversale de la ligne flexible est égale à la dimension transversale du conteneur, ne laissant aucun espace supplémentaire entre les deux. Par conséquent, align-content qui aligne les lignes de flexion lorsqu'il y a un espace supplémentaire dans l'axe transversal n'a aucun effet.

flex-container {
  display: flex;
  flex-wrap: nowrap;
  align-content: center;
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}

<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

enter image description here

Le réglage initial pour align-content est stretch . Cela signifie que si aucune autre valeur n'est spécifiée, le conteneur distribuera l'espace disponible de manière égale entre les lignes de flexion. (Un effet similaire est créé sur l'axe principal lorsque tous les éléments flexibles obtiennent flex: 1 .)

Cette répartition de l'espace entre les lignes peut provoquer de grands écarts entre les lignes / colonnes. Moins de lignes donnent des espaces plus larges. Plus il y a de lignes, plus les écarts sont réduits, car chaque ligne occupe une plus petite partie de l'espace.

Pour résoudre ce problème, passez de align-content: stretch à align-content: flex-start . Les lignes sont ainsi regroupées (voir les exemples 2 et 4 ci-dessus). Bien sûr, cela élimine également tout espace libre dans la ligne, et align-items et align-self ne peut plus travailler.

Voici un billet connexe : Supprimez l'espace (les vides) entre plusieurs lignes d'éléments flexibles lorsqu'ils se referment.

flex-container {
  display: flex;
  flex-wrap: wrap;
  /* align-content: center; */
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}

<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

enter image description here

Comme expliqué dans les exemples précédents, avec align-content: stretch il peut y avoir un espace supplémentaire dans les lignes flexibles, ce qui permet align-items et align-self pour travailler. Toute autre valeur pour align-content remplirait les lignes, éliminant l'espace supplémentaire, et rendant align-items et align-self inutile.

flex-container {
  display: flex;
  flex-wrap: wrap;
  /* align-content: center; */
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}

flex-item:nth-child(even) {
  align-self: flex-end;
  background-color: crimson;
}

<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

3 votes

Bonne explication pour align-content : La propriété align-content modifie le comportement de la propriété flex-wrap. Elle est similaire à align-items, mais au lieu d'aligner les éléments flex, elle aligne les lignes flex.

2 votes

Après avoir commencé à apprendre le flex, puis à le comprendre, puis enfin à découvrir que le chrome se comporte différemment sur les appareils mobiles, j'ai abandonné, maintenant je regrette que je serais devenu un spécialiste des fusées avec autant d'efforts lol.

1 votes

Bonne réponse. Cependant, l'ajout d'un troisième axe (axe z) au diagramme des axes n'était pas du tout nécessaire et ne fait que compliquer les choses.

6voto

vals Points 12518

Tout d'abord, align-content est inutile s'il n'y a pas de wrap :

doc w3c

La propriété align-content aligne les lignes d'un conteneur flex à l'intérieur du conteneur flex lorsqu'il y a un espace supplémentaire dans l'axe transversal, de la même manière que justify-content aligne les éléments individuels dans l'axe principal. Notez que cette propriété a aucun effet sur un conteneur flex d'une seule ligne.

De plus, dans votre deuxième cas, l'alignement de soi n'est pas défaillant. C'est inutile parce que les lignes intérieures ont été tassées. Créons un espace pour que le style puisse fonctionner :

flex-container {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
flex-item:last-child {
  align-self: flex-end;
  background-color: crimson;
}
flex-item:nth-child(5) {
  height: 90px;  /* added */
}

<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

De même, dans votre quatrième exemple, le style fonctionne, si vous définissez les conditions dans lesquelles il peut être vu.

flex-container {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
flex-item:nth-child(2),flex-item:nth-child(5) {
  height: 90px;  /* added */
}

<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Enfin, lorsque vous commentez le align-content, il redevient extensible C'est pourquoi les lignes augmentent la taille pour remplir le conteneur.

étirer Les lignes s'étirent pour occuper l'espace restant. Si l'espace libre restant est négatif, cette valeur est identique à flex-start. Sinon, l'espace libre est réparti de manière égale entre toutes les lignes, ce qui augmente leur taille transversale.

3 votes

Concernant la première phrase, il serait probablement préférable de dire s'il n'y a pas de wrap, il n'y a qu'une seule ligne, et alors align-content est inutile . Je ne suis pas assez bon pour expliquer les choses en anglais ...

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