在 flex break 时更改文本对齐方式

Change text alignement upon flex break

我正在编写一个应该响应的表单,也就是说,当浏览器 window 很小时,左侧标签 "jumps" 位于顶部(参见下面的示例,删除 text-align 属性 并调整浏览器大小)。

现在,当标签文本左对齐时效果很好。 对于可用性问题,我希望标签右对齐(我不希望它们离输入框太远)但是一旦 flex 包裹起来,我就不再希望它们右对齐了。

示例代码:https://jsfiddle.net/xhtfqbzL/

.cont {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}
span
{
  flex: 1 0 20vw;
  text-align: right;
  display: inline-block;
  padding-right: 0.5em;
}
input
{
  flex: 1 1 20rem;
  display: inline-block;
}
<div class='cont'>
<span>Label</span>
<input type="text" placeholder="content">
</div>

那么如何实现这个效果呢?

这里有一个hack要谨慎使用(或者根本不用...)

.cont {
  display: flex;
  flex-wrap: wrap;
  overflow: hidden;
}

.cont:before {
  content: "";
  flex: 1 0 20vw;
  height: 1.2em;
}

span {
  flex: 1 1 20rem;
  position: relative;
}

span:before,
span:after {
  content: attr(data-text);
  position: absolute;
  padding-right: 0.5em;
}

span:before {
  left: 0;
  bottom: 100%;
}

span:after {
  top: 0;
  right: 100%;
}

input {
  width: 100%;
}
<div class='cont'>
  <span data-text="Label">
  <input type="text" placeholder="content">
  </span>
</div>

现在,我最好的尝试是:

   html, body { padding: 0; margin: 0 }
   .cont
{
    display: flex;
    flex-wrap: wrap;
    flex-direction: row;
}

.cont span, .cont input
{
    display: inline-block;
}

.cont span
{
    box-sizing: border-box;
    text-align: right;
    background: blue;
    flex: 1 0 20rem;
}
@media screen and (max-width: 40rem) { 
    .cont span { text-align: left; }
}

.cont input
{
    background: green;
    flex: 1 1 50vw;
    box-sizing: border-box;
}
<div class='cont'>
    <span>Some Label</span>
    <input type="text" value="Text here">
</div>

我不想有媒体查询,因为找到突破点总是很痛苦(这可能会根据设计更改或设备演变而演变)。在这里,我 仍然 使用了媒体查询,但 40rem 魔法值是计算出来的,而不是手动选择的。 通常,表单的行项目之一具有固定大小,另一个相对于视口大小。在此示例中,固定大小为 20rem.

由于它们是弹性项目,当它们不再适合这一行时,它们将换行,即当它们的宽度达到它们的 flex-basis 属性.

因此,行的宽度是span_width[20rem] + input_width[50% * w] = 100% * w 我推断它们会在 100% w = 50% w + 20rem => 50%w = 20rem => w = 40rem

时换行

所以当视口的宽度小于 40rem 时它们会换行。

这样做的主要问题是您必须知道这些项目周围的确切边距和填充大小,这确实很难维护。

另一种不使用媒体查询的解决方案:

   html, body { padding: 0; margin: 0 }
#test
{
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    flex-direction: row;
}
#test p
{
    flex: 0 1 20rem;
    padding:0;
    margin:0;
}
#test p s
{
    width: calc((48vw - 100%) * 5000);
    min-width: 1%;
    max-width: 16rem;
    
    display: inline-block;
    background: salmon;
    height: 1rem;
}
#test p span
{
    background: red;
    padding-right: 0.5rem;
}
#test b
{
    flex: 1 0 50vw;
    background: yellow;
}
<div id="test">
    <p>
        <s></s>
        <span>First</span>
    </p>
    <b>Second</b>
</div>

这是这样工作的:

  1. 标签分为 2 个内联元素,一个 spacer 和标签本身。
  2. spacer使用的是四大绝招,即计算出width属性在+infinite-infinite之间震荡顺序受 min-widthmax-width.
  3. 约束
  4. 断点设置在 flex 行的第 2 项(在示例中,window_width:100vw - input_width:50vw):当标签的剩余尺寸小于行的最小宽度时,其 max-width 属性 被使用,这添加了一个“space”将标签元素推到右边。当 flex 行换行时,左边的大小现在非常大并且在断点之上,因此 min-width 被选中(在我的示例中,我使用了 1% 但它可以是 0%,也就是标签左边几乎没有“边距”)。

此技术的注意事项是您必须添加一个元素(可能可以在此处使用 ::before 伪元素来完成)并且您必须将 max-width 设置为小于 parent width - label width. 这一点使得这个解决方案很难维护。