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

Posted

技术标签:

【中文标题】将图标垂直对齐第一行文本的中心【英文标题】:Align icon vertically to the center of the first line of text 【发布时间】:2015-11-14 01:57:54 【问题描述】:

这是具有align-items: center 属性的眼睛。它们适用于单行文本,适用于多行文本:

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

我想要实现的是:

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

是否可以使用 flexbox 属性优雅地做到这一点,而不使用填充或边距?

(这是一个简化的例子。在真正的问题中我不想引入填充,因为它会影响其他项目。)

这里是 jsfiddle 玩:http://jsfiddle.net/sqp1wdap/

【问题讨论】:

【参考方案1】:

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

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

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

这是 react 的一个例子(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;
`;

【讨论】:

【参考方案2】:

当然,如果图标高度等于行高,它将与第一行“对齐”。

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

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

所以在你的例子中(我只是为了清楚起见夸大了高度,你也可以尝试使用非常小的值,比如 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 */

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

Fiddle 适用于行高大于图标的情况:http://jsfiddle.net/ofdwemva/

小提琴适用于行高小于图标的情况:http://jsfiddle.net/ofdwemva/1/

【讨论】:

最佳答案...其他解决方案非常长,但我不知道为什么必须设置高度,你不能只使用 flex-direction 列吗?【参考方案3】:

我找到了解决方案,而无需更改文本的 line-height 属性。

    与之前的oluckyman's answer 相同,将眼睛和文本都对齐到flex-start。 在 Eye 上添加隐藏的伪元素,类似于文本的高度。 对 Eye 使用 center 对齐,这将对齐 Eye 本身和我们创建的伪元素。

这是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。

【讨论】:

这不是只有在图标小于行高时才有效吗?【参考方案4】:
.LegendItem_Eye 
  width: $slotWidth; // keep width
  float:left; // float left
  line-height:1.3; // define line height
 

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

【讨论】:

【参考方案5】:

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

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

由于 眼睛 图标是方形的,您只需将 height: $slotWidth 添加到 .LegendItem_Eye 和 flex 即可。

因为图标现在被限制在一个小方块内,flex 根本没有空间在它的容器中放置 center 它并根据父规则 @987654328 将其显示在 start @。

Fiddle。

加法

实际上,图标仍以.LegendItem_Eye 为中心,因为它有$slotWidth = $itemHeight = $fontSize * 1.3; 可移入,但我们将其限制在$slotWidth 正方形而不是整个父高度。

逻辑

    flexed 项目的默认值为align-self: stretch.LegendItem 有规则align-items: stretch.LegendItem 有规则justify-content: flex-startalign-self 优先于父 align-items.LegendItem_Eye 没有设置高度值 子.LegendItem_Eye 有规则align-items: center 眼睛-icon 是孩子.LegendItem_Eye的孩子 eye-icon 是一个字体字符,就像字母表中的任何其他字符一样,所以它只占用给定的$fontSize 空间并采用fa fa-eye 字体设置

导致

    child .LegendItem_Eye 因为 1, 2, 4 而增长到父高度 和 5 眼睛-图标位于.LegendItem_Eye 的中心,因为是 6、7 和 9

解决方案

    用值$slotWidth约束孩子.LegendItem_Eye的高度

    纠正5 限制9的增长 和取消10的视觉效果

    因为.LegendItem_Eye的3个孩子眼睛-图标会向上移动

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

【讨论】:

但是justify-content 是水平对齐图标,而不是垂直对齐,所以我不确定这是否解决了问题。 检查小提琴。并且图标位于“row nowrap”元素内,所以它可以做的就是“向上”... 之前图标在自己的元素空间中居中,这是整个父级高度,但现在它在父级内部移动,这就是区别。 为什么是 $fontSize * 1.3? 1.3从何而来? 这是在元素周围添加一些“填充”的巧妙技巧。您现在所要做的就是将其居中。 (不是我的作品,顺便说一句,在原版中)【参考方案6】:

我找到了解决办法:http://jsfiddle.net/sqp1wdap/3/

    将眼睛和文本对齐到flex-start 使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)

下面是它的样子:

【讨论】:

假设您可以确定行高与文本的高度相同,但对于 99% 而言,这不是设计的内容...... 不是一个很好的解决方案。 line-height 不应该依赖于 icon 的大小,应该留给设计师来决定。请参阅@gztomas 的回答以获得更灵活的解决方案。如果您的图标是字体大小的两倍,则此解决方案根本不起作用。【参考方案7】:

我不确定flex 是否有一种优雅的方法,但我可以为您提供同样的方法,并且据我猜测不会影响任何其他元素:

您可以为 font-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

【讨论】:

感谢您的回答。有趣的解决方案。但我找到了我需要的东西:***.com/a/32119917/823778

以上是关于将图标垂直对齐第一行文本的中心的主要内容,如果未能解决你的问题,请参考以下文章

如何将箭头图标垂直对齐到中心

将图标与多行 UILabel 的左上角对齐

如何在 Bootstrap 4 中将 Font-Awesome 图标与一行文本垂直对齐?

如何将 Qlistwidgetitem 文本与图标垂直对齐?

如何正确对齐社交页脚和页脚菜单的中心?

垂直文本对齐多行