对齐双重包裹的嵌套 flex

Posted

技术标签:

【中文标题】对齐双重包裹的嵌套 flex【英文标题】:Aligning a doubly wrapped nested flex 【发布时间】:2021-03-20 20:34:24 【问题描述】:

我正在尝试构建一个包含图像和随附文本描述的响应式画廊。图像和它们的文本应该并排放置在同一行,除非宽度太小并且所有内容都折叠成一列。我唯一的问题是在单列模式下,我希望图像的左侧与更宽的文本对齐。其他一切都按照我的意愿完美对齐和居中。

我知道 flex 不应该做我想做的事,我尝试用网格替换内部 flex,但无法使其工作。我很乐意了解解决此问题的最简单方法(最好不使用媒体查询),更一般地说,正确的方法是什么。最重要的是,我不想被要求引入新的任意数字,除了图像的宽度、文本元素的宽度以及给定的间隙。我会猜到这样的设计会是一个足够常见的用例,但显然缺乏正确的术语,我找不到参考实现。

https://jsfiddle.net/tj13y7sc

编辑:在我看来最有希望的方向:

    简单的解决方法:使图像与文本具有相同的宽度,并在它们位于同一行时使用负 (?) 边距来修复水平间隙。 正确的做法是:用网格替换内部 flex - 但我无法让它一直不折叠。

4 列 - 好:

2 列 - 好:

1 列 - 未对齐:

.flex_container 
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  gap:64px 128px;


.flex_container_item 
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  gap:64px;


.text width:360px;
<div class="flex_container">
  <div class="flex_container_item">
    <img src="https://via.placeholder.com/250" width=256>
    <div class="text">
      <h1>description1</h1>
      <p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </div>
  </div>
  <div class="flex_container_item">
    <img src="https://via.placeholder.com/250" width=256>
    <div class="text">
      <h1>description2</h1>
      <p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </div>
  </div>
    <div class="flex_container_item">
    <img src="https://via.placeholder.com/250" width=256>
    <div class="text">
      <h1>description3</h1>
      <p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </div>
  </div>
  <div class="flex_container_item">
    <img src="https://via.placeholder.com/250" width=256>
    <div class="text">
      <h1>description4</h1>
      <p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </div>
  </div>

</div>

【问题讨论】:

【参考方案1】:

由我解决!

    用名为“image”的 div 包装 img。 将 div“图像”宽度设置为 360 像素(与文本相同) - 这将修复单列模式,但现在间距太大了 360-256=104 像素。 要解决此问题,我们将添加到图像和文本 div:margin: 0 -52px; - 这将通过 -52*2=-104 修复装订线,同时保持所有内容对称。 最后我们将margin: 0 52px;添加到.flex_container_item中,以抵消上一步对外边距的影响。

https://jsfiddle.net/yt0pfnje/

要点:

    永不放弃。永不投降。我很惭愧地承认我为此付出了多少时间。但是,嘿,现在我知道如何使用 flex、grid 和 margin。 如果 gap 可以取负值,这会容易得多。任何人都可以帮助向规范提出这个建议吗? 我仍然无法使其与网格一起使用。我认为由于自动填充的工作方式,这是不可能的 CSS 已损坏。它不应该那么困难。应该不会花这么长时间来解决。其他尝试的答案是由一流的网络专家提出的,他们仍然无法正确回答。我现在相信没有更简单的方法了。但应该有。

【讨论】:

嘿,我已经检查了您的解决方案,您的解决方案不适用于它提供滚动的移动屏幕。我的代码适用于每个设备屏幕。我共享屏幕截图以查看代码。这是链接。您的代码视图:cdn.discordapp.com/attachments/703467645139419197/… 我的代码视图:cdn.discordapp.com/attachments/703467645139419197/… 你给margin -104的解决方案不如我的完美。 感谢您的有益评论。你提出了一些我在我的问题定义中没有考虑到的好点,而且你似乎也解决了这些问题。事实上,我最初的方法在设计上突破了 360 像素,因为我使用的是高达 360 像素的固定宽度元素。此外,我接受的答案中的负边距方法阻止了您建议使用最大宽度的简单修复。但是,width 请注意,我的答案已被反复编辑,违反了我的意愿。你可以在这里阅读我的原文:***.com/revisions/65365617/4【参考方案2】:

现在我只想知道我将&lt;img&gt; 绑定到&lt;div class="image"&gt; &lt;/div&gt; 中,然后进行一些CSS 更改,并添加一个媒体查询以实现响应性。

我还在 CSS 文件中添加了我所做的更改。

下面是你想要的代码sn-p。

.flex_container 
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 64px 128px;


.flex_container_item 
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 64px;


.text 
  width: 100%;
  /*value change*/
  max-width: 360px;
  /*new property add*/



/*new code added*/


/*use 720px media width because we have to fix .image class width same as we have already set for .text class so that they align at the same edge. so now total width for both the blocks is 360px + 360px = 720px.*/

@media(max-width: 720px) 
  .image 
    width: 100%;
    max-width: 360px;
  
<div class="flex_container">
  <div class="flex_container_item">
    <div class="image">
      <img src="https://via.placeholder.com/250" width=256>
    </div>
    <div class="text">
      <h1>description1</h1>
      <p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
        dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </div>
  </div>
  <div class="flex_container_item">
    <div class="image">
      <img src="https://via.placeholder.com/250" width=256>
    </div>
    <div class="text">
      <h1>description2</h1>
      <p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
        dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </div>
  </div>
  <div class="flex_container_item">
    <div class="image">
      <img src="https://via.placeholder.com/250" width=256>
    </div>
    <div class="text">
      <h1>description3</h1>
      <p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
        dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </div>
  </div>
  <div class="flex_container_item">
    <div class="image">
      <img src="https://via.placeholder.com/250" width=256>
    </div>
    <div class="text">
      <h1>description4</h1>
      <p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
        dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </div>
  </div>
</div>

【讨论】:

@eyaler 你检查了这个答案吗,它对你有用吗? 似乎工作,虽然我仍然不确定为什么它应该是 720px 使用 720px 媒体宽度,因为我们必须修复 .image 类宽度,因为我们已经为 .text 类设置了相同的宽度,因此两个类的宽度相同 360px,所以现在两个框的内容在同一边缘对齐。所以现在两个块的总宽度是 .image 类宽度 360px + .text 类宽度 360px = 总宽度 720px。【参考方案3】:

只需将第二个类 justify-content 改为“left”为:

.flex_container_item 
      display:flex;
      flex-wrap:wrap;
      justify-content:left;
      gap:64px;
    

Here's what it looks like(这里还不允许上传图片..)

【讨论】:

这使得一切都是合理的。但文本应该居中。【参考方案4】:

似乎添加下一个条件可能会解决问题 -

.flex_container_item img 
  border: 1px solid blue; /* just for test */
  margin-left: 0;
  margin-right: auto;

请看这里:https://codepen.io/elicohenator/pen/MWjpgze

【讨论】:

这会将图像对齐到窗口的左侧,而我希望它对齐到(居中)文本的左侧。 好吧,这很难做到,因为文本的宽度是恒定的,而图像不是...... 图像的宽度恒定为 256 嗯,布局不常见,但您可以在此处查看更新后的 codepen:codepen.io/elicohenator/pen/MWjpgze 这会改变图像和文本在同一行时的间距,而且在其他一些情况下会出现奇怪的布局 - 请参阅:imgur.com/a/RgwsIMM【参考方案5】:

&lt;img&gt; 标签周围加上这样的 div:

  <div class="flex_container">
      <div class="flex_container_item">
        <div class="image">
          <img src="https://via.placeholder.com/250" width=256>
        </div>
        <div class="text">
.
.
.

并添加到 css:

    .image 
      width:360px
    

像这样: https://jsfiddle.net/860c4tfj/

【讨论】:

这会在图像和文本位于同一行的情况下改变它们之间的间距。如前所述,我的问题是图像和文本的宽度不同 它可能已经能够以负差距解决它。但似乎负差距不是问题 可能是负边距?【参考方案6】:

你的 img 和 div 文本容器的宽度不同,尝试保持相同,它会正确对齐。

或者,如果您想要特定宽度的文本容器。 然后使用媒体查询并将 flex-direction 更改为列以用于较小的屏幕。

【讨论】:

确实图片应该比文字更薄 那么您可以使用媒体查询来获得更小的屏幕,并更改 flex-direction 以获得更小的尺寸。 ` @media only screen and (max-width: 600px) .flex_container_item flex-direction: column; ` codesandbox.io/s/flex-box-align-issue-n6t6o?file=/index.css 通过调整窗口大小或缩小来检查此项 600px的计算方法是什么? 600 似乎并未涵盖所有情况。在媒体查询开始之前我得到一列 这只是我提供的值,例如,根据您的设计提供值。在转换为单列时检查断点并提供该值。

以上是关于对齐双重包裹的嵌套 flex的主要内容,如果未能解决你的问题,请参考以下文章

Flex:选择包裹的flex中每一行的第一个和最后一个项目

Inline-Flex 与垂直对齐混乱

Flex:对齐按钮向右对齐,内容向左对齐

flex多行多列两端对齐,列不满左对齐

flex布局第一行div左对齐,第二行中对齐,第三行右对齐

理解flex_对齐