将图标垂直对齐到第一行文本的中心

Align icon vertically to the center of the first line of text

这是 align-items: center 属性 的眼睛。它们对单行文本有效,对多行文本失败:

这是align-items: baseline(或flex-start)的眼睛。它们更适合多行文本,但并不适合所有文本,因为我想将视线对准文本第一行的中心:

我想要实现的是:

看到眼睛图像如何在文本的第一行居中了吗?

是否可以使用 flexbox 属性优雅地完成它,而不使用填充或边距?

(这是一个简化的例子,在实际问题中我不想引入padding,因为它会影响其他项。)

这里是可以玩的 jsfiddle:http://jsfiddle.net/sqp1wdap/

我不确定 flex 是否有一种优雅的方式来做到这一点,但我可以为您提供相同的破解方法,据我所知,这不会影响任何其他元素:

您可以为字体添加自定义样式-awesome.css

.fa{
    position: absolute;
    top: 0;
    left: 0;
    text-align:center;
    padding:3px;
}

对于您的自定义样式,您可以这样做:

.LegendItem_Eye {
  width: $slotWidth;
  display: flex;
  justify-content: center;
  align-items: center;
  background: #eee;
  position: relative; /* Added this new rule */
}

我知道这不是正确的解决方案,但您可以尝试一下,除非它会损害其他元素。 :)

jSFiddle

我找到了解决方案:http://jsfiddle.net/sqp1wdap/3/

  1. 将眼睛和文本都对齐 flex-start
  2. 使文本 line-height 与眼睛高度相同

这是编辑后的代码:

.LegendItem_Eye {
  width: $slotWidth;
  display: flex;
  justify-content: center;
  align-items: flex-start; // ← edit (1)
  background: #eee;
}
.LegendItem_Text {
  padding: 0 3px;
  flex: 1;
  align-self: flex-start; // ← edit (1)
  background: #eaa;
  line-height: $fontSize; // ← edit (2)
}

这是它的样子:

(2017 年 7 月)虽然解决方案(和其他答案)起到了作用,但他们都错过了最直接、最容易修改的答案。

首先将 * { outline: 1px dashed } 添加到原始的、未修改的 Fiddle 中,你几乎可以看到解决方案正对着你,因为元素 .LegendItem_Eye 占据了 [= 的整个高度137=]容器。

由于 eye-icon 是方形的,您可以简单地将 height: $slotWidth 添加到 .LegendItem_Eye,剩下的由 flex 完成。

因为图标现在被限制在一个小方块内,flex根本没有空间将它center放在它的容器中并显示在start 根据 parent 规则 justify-content: flex-start.

Fiddle.

加法

实际上,图标仍然位于 .LegendItem_Eye 的中心,因为它有 $slotWidth = $itemHeight = $fontSize * 1.3; 可以移动,但我们将其限制在 $slotWidth 正方形而不是完整的 parent身高。

逻辑

  1. flexed 项的默认值为 align-self: stretch
  2. parent .LegendItem 有规则 align-items: stretch
  3. parent .LegendItem 有规则 justify-content: flex-start
  4. child align-self 优先于 parent align-items
  5. child .LegendItem_Eye 没有设置高度值
  6. child .LegendItem_Eye 有规则 align-items: center
  7. 眼睛-图标是child的child.LegendItem_Eye
  8. eye-icon 是一个字体字符,就像字母表中的任何其他字符一样,所以它只占用给定的 $fontSize space 并占用fa fa-eye字体设置

导致

  1. child .LegendItem_Eye 长到 parent 因为 1, 2, 4 和 5
  2. eye-图标居中 .LegendItem_Eye 因为 6、7 和 9

解决方案

  1. 用值 $slotWidth

    限制 child .LegendItem_Eye 的高度
    • 更正 5
    • 限制9的增长
    • 并取消10的视觉效果
  2. 因为.LegendItem_Eye的3个child 眼睛-图标会上移

所有规则 1 到 8(规则 5 除外)仍然有效,只是被 $slotWidth

.LegendItem_Eye {
  width: $slotWidth; // keep width
  float:left; // float left
  line-height:1.3; // define line height
} 

这应该是您需要的全部Demo.

我找到了解决方案,没有改变文本的 line-height 属性。

  1. 和之前的一样,眼睛和文字都对齐flex-start
  2. 在 Eye 上添加隐藏的伪元素,使其与 Text 的高度相似。
  3. 对眼睛使用 center 对齐,这将使眼睛本身与我们创建的伪元素对齐。

这是 link 到 JSFiddle 以及我所做工作的总结:

.LegendItem {
  min-height: $itemHeight;
  font-size: $fontSize;
  margin: 2px 0;

  display: flex;
  flex-flow: row nowrap;
  justify-content: flex-start;
  align-items: flex-start;  // <-- Change this
}

.LegendItem_Eye {
  width: $slotWidth;
  display: flex;
  justify-content: center;
  align-items: center;
  background: #bbb;
}
.LegendItem_Eye::before {   // <-- Add this
  content: "A";
  width: 0px;
  visibility: hidden;
}

.LegendItem_Text {
  padding: 0 3px;
  flex: 1;
  background: #eaa;         // <-- Remove align-self
}

它看起来像 this。

当然,如果图标高度等于行高,则'aligned'到第一行。

通常情况下,这两者会有所不同。您实际上无法在不影响视觉设计的情况下更改行高或图标高度。

因此解决方案是用高度等于文本 line-height 的弹性容器包裹图标。这个容器将做图标的垂直居中。如果图标比容器大那么它就会从顶部和底部溢出。

所以在你的例子中(为了清楚起见,我只是夸大了高度,你也可以尝试使用非常小的值,比如 8px,看看它在两种情况下的工作原理)

.LegendItem_Eye {
  width: $slotWidth;
  display: flex;
  justify-content: center;
  align-items: center;
  background: #eee;
  height: 100px; /* <-- set this */
}

.LegendItem_Text {
  padding: 0 3px;
  flex: 1;
  background: #eaa;
  line-height: 100px; /* <-- equal to this, no need to set this, just use right value above */
}

请注意,您实际上不需要更改文本 line-height,只需将眼睛容器的高度设置为该值即可。

Fiddle 适用于 line-height 大于图标的情况:http://jsfiddle.net/ofdwemva/

Fiddle 适用于 line-height 小于图标的情况:http://jsfiddle.net/ofdwemva/1/

这里的很多答案将取决于您的情况 - 当前(和错误地)接受的答案只有在您的设计师不介意您削减对大多数人不利的行高时才有效。

如果您想最终做到这一点,您的目标是让图标容器与一行文本高度相同,然后将此容器内的图标居中对齐。

这样做的一个不错的方法是复制一些与您想要居中的文本具有相同 css 的文本,然后将其隐藏,这将确保容器现在具有相同的高度作为文本。现在您只需将图标居中对齐即可。

这是一个反应中的例子(css是一样的)


export function CheckmarkListItem({ point }: Iprops) {
    return (
        <Div>
            <IconContainer>
                <SvgWrap size={20} mixin={svgMix}>
                    <Checkmark />
                </SvgWrap>
                <HiddenDiv>
                    <Typo tag="p">Mock text</Typo>
                </HiddenDiv>
            </IconContainer>
            <PointDiv>
                <Typo tag="p">{point}</Typo>
            </PointDiv>
        </Div>
    );
}
const Div = styled.div`
    display: flex;
    text-align: left;
    gap: 15px;
    ${(props) => props.theme.breakpoints.up.md} {
        gap: 30px;
    }
    align-items: flex-start;
`;

const PointDiv = styled.div``;

const IconContainer = styled.div`
    display: flex;
    align-items: center;
`;
const svgMix = css`
    margin: 0;
`;

const HiddenDiv = styled.div`
    visibility: hidden;
    width: 0;
`;