Quantcast
Channel: w3cplus
Viewing all articles
Browse latest Browse all 1557

聊聊Flexbox布局中的flex的演算法

$
0
0

到目前为止,Flexbox布局应该是目前最流行的布局方式之一了。而Flexbox布局的最大特性就是让Flex项目可伸缩,也就是让Flex项目的宽度和高度可以自动填充Flex容器剩余的空间或者缩小Flex项目适配Flex容器不足的宽度。而这一切都是依赖于Flexbox属性中的flex属性来完成。一个Flex容器会等比的按照各Flex项目的扩展比率分配Flex容器剩余空间,也会按照收缩比率来缩小各Flex项目,以免Flex项目溢出Flex容器。但其中Flex项目又是如何计算呢?他和扩展比率或收缩比率之间又存在什么关系呢?在这篇文章中我们将一起来探来。

在Flexbox布局中,容器中显示式使用display设置为flexinline-flex,那么该容器就是Flex容器,而该容器的所有子元素就是Flex项目。

简介

在这篇文章中,我们将要聊的是有关于flex属性的事情,特别是如何使用该属性来计算Flex项目?在开始之前,先来简单的了解一下flex属性。

在Flexbox中,flex属性是flex-grow(扩展比率)、flex-shrink(收缩比率)和flex-basis(伸缩基准)三个属性的简称。这三个属性可以控制一个Flex项目(也有人称为Flex元素),主要表现在以下几个方面:

  • flex-grow:Flex项目的扩展比率,让Flex项目得到(伸张)多少Flex容器多余的空间(Positive free space)
  • flex-shrink:Flex项目收缩比率,让Flex项目减去Flex容器不足的空间(Negative free space)
  • flex-basis:Flex项目未扩展或收缩之前,它的大小是多少

在Flexbox布局中,只有充分理解了这三个属性才能彻底的掌握Flex项目是如何扩展和收缩的,也才能更彻底的掌握Flexbox布局。因此掌握这三个属性,以及他们之间的计算关系才是掌握Flexbox布局的关键所在。

相关概念

在具体介绍flex相关的技术之前,先对几个概念进行描述,因为理解了这几个概念更有易于大家对后面知识的理解。

主轴长度和主轴长度属性

Flex项目在主轴方向的宽度或高度就是Flex项目的主轴长度,Flex项目的主轴长度属性是widthheight属性,具体是哪一个属性,将会由主轴方向决定。

剩余空间和不足空间

在Flexbox布局中,Flex容器中包含一个或多个Flex项目(该容器的子元素或子节点)。Flex容器和Flex项目都有其自身的尺寸大小,那么就会有:Flex项目尺寸大小之和大于或小于Flex容器情景:

  • 当所有Flex项目尺寸大小之和小于Flex容器时,Flex容器就会有多余的空间没有被填充,那么这个空间就被称为Flex容器的剩余空间(Positive Free Space)
  • 当所有Flex项目尺寸大小之和大于Flex容器时,Flex容器就没有足够的空间容纳所有Flex项目,那么多出来的这个空间就被称为负空间(Negative Free Space)

举个例子向大家阐述这两个情形:“假设我们有一个容器(Flex容器),显式的给其设置了width800pxpadding10px,并且box-sizing设置为border-box”。根据CSS的盒模型原理,我们可以知道Flex容器的内宽度(Content盒子的宽度)为800px - 10px * 2 = 780px

假设Flex容器中包含了四个Flex项目,而且每个Flex项目的width都为100px,那么所有Flex项目的宽度总和则是100px * 4 = 400px(Flex项目没有设置其他任何有关于盒模型的尺寸),那么Flex容器将会有剩余的空间出来,即780px - 400px = 380px。这个380px就是我们所说的Flex容器的剩余空间:

假设把Flex项目的width100px调到300px,那么所有Flex项目的宽度总和就变成了300px * 4 = 1200px。这个时候Flex项目就溢出了Flex容器,这个溢出的宽度,即1200px - 780px = 420px。这个420px就是我们所说的Flex容器的不足空间:

上面演示的是主轴在x轴方向,如果主轴变成y轴的方向,同样存在上述两种情形,只不过把width变成了height接下来的内容中,如果没有特殊说明,那么所看到的示例都仅演示主轴在x轴的方向,即flex-directionrow

min-content 和 max-content

min-contentmax-content是CSS中的一个新概念,隶属于CSS Intrinsic and Extrinsic Sizing Specification模块。简单的可以这么理解。

CSS可以给任何一个元素显式的通过width属性指定元素内容区域的宽度,内容区域在元素paddingbordermargin里面。该属性也是CSS盒模型众多属性之一。

记住,CSS的box-sizing可以决定width的计算方式。

如果我们显式设置width为关键词auto时,元素的width将会根据元素自身的内容来决定宽度。而其中的min-contentmax-content也会根据元素的内容来决定宽度,只不过和auto有较大的差异

  • min-content: 元素固有的最小宽度(内容)
  • max-content: 元素固有的最大宽度(内容)

比如下面这个示例:

如果内容是英文的话,min-content的宽度将取决于内容中最长的单词宽度,中文就有点怪异(其中之因目前并未深究),而max-content则会计算内容排整行的宽度,有点类似于加上了white-space:nowrap一样。

上例仅展示了min-contentmax-content最基本的渲染效果(Chrome浏览器渲染行为)。这里不做深入的探讨论,毕竟不是本文的重点,如果感兴趣,欢迎关注后续的相关更新,或者先阅读@张鑫旭 老师写的一篇文章《理解CSS3 max/min-contentfit-contentwidth

回到我们自己的主题上来。

前面在介绍Flex剩余空间和不足空间的时候,我们可以得知,出现这两种现象取决于Flex容器和Flex项目的尺寸大小。而flex属性可以根据Flex容器的剩余空间(或不足空间)对Flex项目进行扩展(或收缩)。那么为了计算出有多少Flex容器的剩余空间能用于Flex项目上,客户端(浏览器)就必须知道Flex项目的尺寸大小。要是没有显式的设置元素的width属性,那么问题就来了,浏览器它是如何解决没有应用于绝对单位的宽度(或高度)的Flex项目,即如何计算?

这里所说的min-contentmax-content两个属性值对于我们深入的探讨flex属性中的flex-growflex-grow属性有一定的影响。所以提前向大家简单的阐述一正是这两个属性值在浏览器中的渲染行为。

简单的总结一下:min-content的大小,从本质上讲,是由字符串中最长的单词决定了大小;max-content则和min-content想反. 它会变得尽可能大, 没有自动换行的机会。如果Flex容器太窄, 它就会溢出其自身的盒子!

Flex项目的计算

在Flexbox布局当中,其中 flex-growflex-shrinkflex-basis都将会影响Flex项目的计算。接下来我们通过一些简单的示例来阐述这方面的知识。

flex-basis

flex-basis属性在任何空间分配发生之前初始化Flex项目的尺寸。其默认值为auto。如果flex-basis的值设置为auto,浏览器将先检查Flex项目的主尺寸是否设置了绝对值再计算出Flex项目的初始值。比如说,你给Flex项目设置的width200px,那么200px就是Flex项目的flex-basis值。

如果你的Flex项目可以自动调整大小,则auto会解析为其内容的大小,这个时候,min-contentmax-content变会起作用。此时将会把Flex项目的max-content作为 flex-basise的值。比如,下面这样的一个简单示例:

flex-growflex-shrink的值都为0,第一个Flex项目的width150px,相当于flex-basis的值为150px,而另外两个Flex项目在没有设置宽度的情况之下,其宽度由内容的宽度来设置。

如果flex-basis的值设置为关键词content,会导致Flex项目根据其内容大小来设置Flex项目,叧怕是Flex项目显式的设置了width的值。到目前为止,content还未得到浏览器很好的支持。

flex-basis除了可以设置autocontentfillmax-contentmin-contentfit-content关键词之外,还可以设置<length>值。如果<length>值是一个百分比值,那么Flex项目的大小将会根据Flex容器的width进行计算。比如下面这个示例:

Flex容器显式设置了width(和box-sizing取值有关系,上图为border-box的示例结果),那么flex-basis会根据Flex容器的width计算出来,如果Flex容器未显示设置width值,则计算出来的结果将是未定义的(会自动根据Flex容器的宽度进行计算)。

在Flexbox布局中,如果你想完全忽略Flex项目的尺寸,则可以将flex-basis设置为0。这样的设置,基本上是告诉了浏览器,Flex容器所有空间都可以按照相关的比例进行分配。

来看一个简单的示例,Flex项目未显式设置width情况之下,flex-basis不同取值的渲染效果:

到写这篇文章为止,使用Firefox浏览器查看效果更佳。

当Flex项目显式的设置了min-widthmax-width的值时,就算Flex项目显式的设置了flex-basis的值,也会按min-widthmax-width设置Flex项目宽度。当计算的值大于max-width时,则按max-width设置Flex项目宽度;当计算的值小于min-width时,则按min-width设置Flex项目宽度:

有关于flex-basis属性相关的运用简单的小结一下:

  • flex-basis默认值为auto
  • 如果Flex项目显式的设置了width值,同时flex-basisauto时,则Flex项目的宽度为按width来计算,如果未显式设置width,则按Flex项目的内容宽度来计算
  • 如果Flex项目显式的设置了width值,同时显式设置了flex-basis的具体值,则Flex项目会忽略width值,会按flex-basis来计算Flex项目
  • 当Flex容器剩余空间不足时,Flex项目的实际宽度并不会按flex-basis来计算,会根据flex-growflex-shrink设置的值给Flex项目分配相应的空间
  • 对于Flexbox布局中,不建议显式的设置Flex项目的width值,而是通过flex-basis来控制Flex项目的宽度,这样更具弹性
  • 如果Flex项目显式的设置了min-widthmax-width值时,当flex-basis计算出来的值小于min-width则按min-width值设置Flex项目宽度,反之,计算出来的值大于max-width值时,则按max-width的值设置Flex项目宽度

flex-grow

前面提到过,flex-grow是一个扩展因子(扩展比例)。其意思是,当Flex容器有一定的剩余空间时,flex-grow可以让Flex项目分配Flex容器剩余的空间,每个Flex项目将根据flex-grow因子扩展,从而让Flex项目布满整个Flex容器(有效利用Flex容器的剩余空间)。

flex-grow的默认值是0,其接受的值是一个数值,也可以是一个小数值,但不支持负值。一旦flex-grow的值是一个大于0的值时,Flex项目就会占用Flex容器的剩余空间。在使用flex-grow时可以按下面的方式使用:

  • 所有Flex项目设置相同的flex-grow
  • 每个Flex项目设置不同的flex-grow

不同的设置得到的效果将会不一样,但flex-grow的值始终总量为1,即Flex项目占有的量之和(分子)和分母相同。我们来具体看看flex-grow对Flex项目的影响。

当所有的Flex项目具有一个相同的flex-grow值时,那么Flex项目将会平均分配Flex容器剩余的空间。在这种情况之下将flex-grow的值设置为1。比如下面这个示例,Flex容器(width: 800pxpadding: 10px)中有四个子元素(Flex项目),显式的设置了flex-basis150px,根据前面介绍的内容,我们可以知道每个Flex项目的宽度是150px,这样一来,所有Flex项目宽度总和为150px * 4 = 600px。容器的剩余空间为780px - 600px = 180px。当显式的给所有Flex项目设置了flex-grow1(具有相同的值)。这样一来,其告诉浏览器,把Flex容器剩余的宽度(180px)平均分成了四份,即:180px / 4 = 45px。而flex-grow的特性就是按比例把Flex容器剩余空间分配给Flex项目(当然要设置了该值的Flex项目),就该例而言,就是给每个Flex项目添加了45px,也就是说,此时Flex项目的宽度从150px扩展到了195px150px + 45px = 195px)。如下图所示:

特别声明,如果Flex项目均分Flex容器剩余的空间,只要给Flex项目设置相同的flex-grow值,大于1即可。比如把flex-grow设置为10,就上例而言,把剩余空间分成了40份,每个Flex项目占10份。其最终的效果和设置为1是等效的。

上面我们看到的均分Flex容器剩余空间,事实上我们也可以给不同的Flex项目设置不同的flex-grow值,这样一来就会让每个Flex项目根据自己所占的比例来占用Flex容器剩余的空间。比如上面的示例,把Flex项目的flex-grow分别设置为1:2:3:4。也就是说把Flex容器的剩余空间分成了10份(1 + 2 + 3 + 4 = 10),而每个Flex项目分别占用Flex容器剩余空间的1/102/103/104/10。就上例而言,Flex容器剩余空间是180px,按这样的计算可以得知,每一份的长度是180px / 10 = 18px,如此一来,每个Flex项目的宽度则变成:

  • Flex1: 150px + 18px * 1 = 168px
  • Flex2: 150px + 18px * 2 = 186px
  • Flex3: 150px + 18px * 3 = 204px
  • Flex4: 150px + 18px * 4 = 222px

最终效果如下图所示:

前面两个示例向大家演示了,Flex项目均分和非均分Flex容器剩余的空间。从示例中可以看出来,flex-grow的值都是大于或等于1的数值。事实上,flex-grow还可以设置小数。比如,给所有Flex项目设置flex-grow的值为0.2。由于Flex项目的flex-grow的值都相等,所以扩展的值也是一样的,唯一不同的是,所有的Flex项目并没有把Flex容器剩余空间全部分完。就我们这个示例而言,四个Flex项目的flex-grow加起来的值是0.8,小于1。换句话说,四个Flex项目只分配了Flex容器剩余空度的80%,按上例的数据来计算,即是180px * .8 = 144px(只分去了144px),而且每个Flex项目分得都是36px144px / 4 = 36px或者 144px * 0.2 / 0.8 = 36px)。最终效果如下图所示:

上面的示例中,flex-basis都显式的设置了值。事实上,flex-growflex-basis会相互影响的。这也令我们的Flex项目计算变得复杂化了。比如说,flex-basis的值为auto,而且没有给Flex项目显式的设置width。根据前面的内容我们可以得知,此时Flex项目的大小都取决于其内容的max-content大小。此时Flex容器的剩余的空间将由浏览器根据Flex项目的内容宽度来计算。比如接下来的这个示例,四个Flex项目都是由其内容max-content大小决定。同时将flex-grow都设置为1(均匀分配Flex容器剩余空间)。具体的数据由下图所示(Chrome浏览器计算得出的值):

特别注意,不同浏览器对小数位的计算略有差异,上图是在Chrome浏览器下得出的值。所以最终加起来的值略大于Flex容器的宽度708px

针对这样的使用场景,如果你想让所有Flex项目具有相同的尺寸,那么可以显式的设置Flex项目的flex-basis值为0flex: 1 1 0)。从flex-basis一节中可以得知,当flex-basis值为0时,表示所有空间都可以用来分配,而且flex-grow具有相同的值,因此Flex项目可以获取均匀的空间。如此一来Flex项目宽度将会相同。

flex-basis还可以由其他值为设置Flex项目的宽度,这里不再一一演示。感兴趣的同学可以自己根据flex-basis的取值写测试用例。换句话说,如果你理解了前面介绍的flex-basis内容,就能更好的理解flex-growflex-basis相结合对Flex项目分配Flex容器剩余空间的计算。也将不会再感到困惑。

flex-shrink

flex-shrinkflex-grow类似,只不过flex-shrink是用来控制Flex项目缩放因子。当所有Flex项目宽度之和大于Flex容器时,将会溢出容器(flex-wrapnowrap时),flex-shrink就可以根据Flex项目设置的数值比例来分配Flex容器的不足空间,也就是按比例因子缩小自身的宽度,以免溢出Flex容器。

flex-shrink接收一个<number>值,其默认值为1。也就是说,只要容器宽度不足够容纳所有Flex项目时,所有Flex项目默认都会收缩。如果你不想让Flex项目进行收缩时,可以设置其值为0,此时Flex项目始终会保持原始的fit-content宽度。同样的,flex-shrink也不接受一个负值做为属性值。

基于上面的示例,简单的调整一下参数,所有Flex项目都设置了flex: 0 0 300px,可以看到Flex项目溢出了Flex容器:

在这个示例中,由于flex-shrink显式的设置了值为0,Flex项目不会进行收缩。如果你想让Flex项目进行收缩,那么可以把flex-shrink设置为1

从上图的结果我们可以看出,当所有Flex项目的flex-shrink都设置为相同的值,比如1,将会均分Flex容器不足空间。比如此例,所有Flex项目的宽度总和是1200pxflex-basis: 300px),而Flex容器宽度是780pxwidth: 800pxpadding: 10px,盒模型是border-box),可以算出Flex容器不足空间为420px1200 - 780 = 420px),因为所有Flex项目的flex-shrink1,其告诉浏览器,将Flex容器不足空间均分成四份,那么每份则是105px420 / 4 = 105px),这个时候Flex项目就会自动缩放105px,其宽度就由当初的300px变成了195px300 - 105 = 195px)。

这个示例演示的是Flex项目设置的值都是相同的值,其最终结果是将会均分Flex容器不足空间。其实flex-shrink也可以像flex-grow一样,为不同的Flex项目设置不同的比例因子。比如1:2:3:4,这个时候Flex项目就不会均分了,而是按自己的比例进行收缩,比例因子越大,收缩的将越多。如下图所示:

就上图而言,所有Flex项目的flex-shrink之和为101 + 2 + 3 + 4 = 10),此时把Flex容器不足空间420px分成了十份,每一份42px420 / 10 = 42px),每个Flex项目按照自己的收缩因子相应的去收缩对应的宽度,此时每个Flex项目的宽度就变成:

  • Flex1: 300 - 42 * 1 = 258px
  • Flex2: 300 - 42 * 2 = 216px
  • Flex3: 300 - 42 * 3 = 174px
  • Flex4: 300 - 42 * 4 = 132px

按照该原理来计算的话,当某个Flex项目的收缩因子设置较大时,就有可能会出现小于0的现象。基于上例,如果把第四个Flex项目的flex-shrink设置为15。这样一来,四个Flex项目的收缩因子就变成:1:2:3:15。也就是说把Flex容器不足空间分成了21份,每份占据的宽度是20px420 / 21 = 20px)。那么Flex项目的宽度就会出现0的现象(300 - 15 * 20 = 0)。这个时候会不会出现无空间容纳Flex项目的内容呢?事实上并不会这样:

在Flexbox布局当中,会阻止Flex项目元素宽度缩小至0。此时Flex项目会以min-content的大小进行计算,这个大小是它们利用任何可以利用的自动断行机会后所变成的

如果某个Flex项目按照收缩因子计算得出宽度趋近于0时,Flex项目将会按照该元素的min-content的大小来设置宽度,同时这个宽度将会转嫁到其他的Flex项目,再按相应的收缩因子进行收缩。比如上例,Flex项目四,其flex-shrink15,但其宽度最终是以min-content来计算(在该例中,Chrome浏览器渲染的宽度大约是22.09px)。而这个22.09px最终按照1:2:3的比例分配给了Flex项目一至三(Flex1,Flex2和Flex3)。对应的Flex项目宽度就变成:

  • Flex1: 300 - 20 * 1 - 22.09 / 6 * 1 = 276.334px
  • Flex2: 300 - 20 * 2 - 22.09 / 6 * 2 = 252.636px
  • Flex3: 300 - 20 * 3 - 22.09 / 6 * 3 = 228.955px
  • Flex4: min-content,在该例中大约是22.09px

对于该情形,计算相对而言就更为复杂一些了。但浏览器会很聪明的帮你处理这些场景,会倾向于给你合理的结果。只不过大家需要知道这样的一个细节,碰到类似的场景才不会一脸蒙逼(^_^)

flex-grow可以设置一个小于1的值,同样的,flex-shrink也可以设置一个小于1的值,比如我们给所有的Flex项目设置flex-shrink的值为0.2,你将看到的结果如下:

从结果的示例图中我们可以看出来,当所有Flex项目的收缩因子(flex-shrink)总和小于1时,Flex容器不足空间不会完全分配完,依旧会溢出Flex容器。好比该例,flex-shrink的总和是.8,分配了Flex容器剩余空间420px80%,即336px(还有84px剩余空间未完全分配完),由于每个Flex项目的收缩因子是相同的,好比前面的示例,都设置了1类似,把分配的空间336px均分为四份,也就是84px,因此每个Flex项目的宽度由当初的300px变成了216px300 - 84 = 216px)。这个其实和flex-grow类似,只不过flex-shrink只是收缩而以。

Flex项目计算公式

Flex项目伸缩计算是一个较为复杂的过程,但它们之间还是有据可查。@Chris@Otree对该方面就有深入的研究。他们给Flex项目的计算总结出了一套计算公式,具体公式如下:

@Chris还依据这套公式写了一个JavaScript的案例,来模拟Flex项目计算:

flex常见的值

大部分情形之下,我们都是使用flex属性来设置Flex项目的伸缩的值。其常见值的效果有:

  • flex: 0 autoflex:initial,这两个值与flex: 0 1 auto相同,也是初始值。会根据width属性决定Flex项目的尺寸。当Flex容器有剩余空间时,Flex项目无法扩展;当Flex容器有不足空间时,Flex项目收缩到其最小值min-content
  • flex: autoflex: 1 1 auto相同。Flex项目会根据width来决定大小,但是完全可以扩展Flex容器剩余的空间。如果所有Flex项目均为flex: autoflex:initialflex: none,则Flex项目尺寸决定后,Flex容器剩余空间会被平均分给是flex:a uto的Flex项目。
  • flex: noneflex: 0 0 auto相同。Flex项目根据width决定大小,但是完全不可伸缩,其效果和initial类似,这种情况下,即使在Flex容器空间不够而溢出的情况之下,Flex项目也不会收缩。
  • flex: <positive-number>(正数)与flex: 1 0px相同。该值使Flex项目可伸缩,并将flex-basis值设置为0,导致Flex项目会根据设置的比例因子来计算Flex容器的剩余空间。如果所有Flex项目都使用该模式,则它们的尺寸会正比于指定的伸缩比。

默认状态下,伸缩项目不会收缩至比其最小内容尺寸(最长的英文词或是固定尺寸元素的长度)更小。可以靠设置min-width属性来改变这个默认状态。

如何掌握Flex项目的大小

通过前面的内容介绍,应该可以了解到Flex项目的大小计算是非常的复杂。如果要真正的理解Flex项目是如何工作的话,最为关键的是理解有多少东西参与影响Flex项目。我们可以按下面这样的方式来进行思考。

怎么设置Flex项目的基本大小

在CSS中设置一个元素的基本大小可以通过width来设置,或者通过min-widthmax-width来设置元素的最小或最大宽度,在未来我们还可以通过contentmin-contentmax-contentfit-content等关键词来设置元素的大小。对于Flex项目,我们还可以通过flex-basis设置Flex项目大小。对于如何设置Flex项目的基本大小,我们可以围绕以下几点来进行思考:

  • flex-basis的值是auto?Flex项目显式的设置了宽度吗?如果设置了,Flex项目的大小将会基于设置的宽度
  • flex-basis的值是auto还是content?如果是auto,Flex项目的大小为原始大小
  • flex-basis的值是0的长度单位吗?如果是这样那这就是Flex项目的大小
  • flex-basis的值是0呢? 如果是这样,则Flex项目的大小不在Flex容器空间分配计算的考虑之内

更为具体的可以参阅flex-basis相关的介绍。

我们有可用空间吗?

如果Flex容器没有剩余空间,Flex项目就不会扩展;如果Flex容器没有不足空间,Flex项目就不会收缩:

  • 所有的Flex项目的宽度总和是否小于Flex容器的总宽度? 如果是这样,那么Flex容器有剩余空间,flex-grow会发挥作用, 具体如何发挥作用,可以参阅flex-grow相关的介绍
  • 所有的Flex项目的宽度总和是否大于Flex容器的总宽度? 如果是这样,那么Flex容器有不足空间,flex-shrink会发挥作用,具体如何发挥作用,可以参阅flex-shrink相关的介绍

分配空间的其他方式

如果我们不想把Flex容器的剩余空间扩展到Flex项目中,我们可以使用Flexbox中其他属性,比如justify-content属性来分配剩余空间。当然也可以给Flex项目设置margin值为处理Flex容器剩余空间。不过这一部分没有在这里阐述,如果感兴趣的话,不仿阅读一下Flexbox相关的介绍。

总结

很久以为,一直以为Flexbox布局中,Flex项目都会根据Flex容器自动计算。而事实上呢?正如文章中介绍的一样,Flex项目的计算是相当的复杂。设置Flex项目大小的值以及flex-basisflex-growflex-shrink的设置都会对其有较大的影响,而且它们的组合场景也是非常的多,并且不同的场景会造成不一样的结果。

当然,文章中所介绍的内容或许没有覆盖到所有的场景,但这些基本的演示或许能帮助大家更好的理解Flex项目是如何计算的。最后希望该文对大家有所帮助,如果你有更深的了解欢迎在下面的评论中与我一起分享。如果文章中有不对之处,还望各路大婶拍正。


Viewing all articles
Browse latest Browse all 1557

Trending Articles