【问题标题】:horizontal scrollable list fully centered with dynamic width items水平滚动列表完全居中动态宽度项目
【发布时间】:2016-07-21 07:00:34
【问题描述】:

我正在尝试使水平列表居中,其项目也相对于主要父级(窗口或主体)居中;而且因为我不知道我将在该列表中生成什么样的项目和多少项目,所以我需要项目的宽度是动态的并且列表可滚动,以便我可以浏览所有项目。

到目前为止,我的尝试都很好,我得到了:一个居中的列表,其中包含动态宽度的非居中项目;以及具有固定宽度项目的完全居中的可滚动列表。

核心思想基本上是通过使用来实现的:

ul {
  width: 100%;
  overflow-x: scroll;
  overflow-y: hidden;
  white-space: nowrap;
}

li {
  display: inline-block;
}

然后通过将<ul> 包裹到<div> 中来进行居中,并使<div> 滚动<ul> 而不是<ul> 滚动<li>。它允许将基于百分比的边距添加到<ul>

div {
  width: 100%;
  overflow-x: scroll;
  overflow-y: hidden;
  white-space: nowrap;
}

ul {
  margin: 0 50%;
}

li {
  display: inline-block;
}

对于按宽度居中的项目,想法是使用 translateX(-50%) 稍加改动:因为我不希望我的列表在滚动结束时有额外的空间,所以我删除了最后一个项目通过将其绝对定位在末尾来从流程中提取;这样,<ul> 的宽度看起来就像项目宽度的总和减去一项。

ul {
  position: relative;
  margin: 0 50%;
}

li {
  display: inline-block;
  width: some_number;
  transform: translateX(-50%);
}

li:last-child {
  position: absolute;
  left: 100%;
}

但是如何在不设置宽度的情况下保持这种状态对我来说是个谜。
有什么想法吗?

这是我在 CSS 部分中对一些 cmets 的摆弄:https://jsfiddle.net/11gkrju0/

我希望为此使用 javascript,因为这只是样式问题,但与 dom 混在一起是一个完全可行的选择。

感谢大家的阅读,

【问题讨论】:

    标签: html css width centering horizontal-scrolling


    【解决方案1】:

    好吧,这有点棘手。解决的小提琴在这里与我将在这里描述的 cmets 一起。 https://jsfiddle.net/11gkrju0/7/

    首先要注意的是,我在<li>s 中添加了一个vertical-align: top;,以确保在某些时候没有垂直间隙。

    那么。

    非居中列表的边界很容易捕捉:

    +-----+---+---------+
    |  A  | B |    C    |
    +-----+---+---------+
    ^                   ^
    a                   b
    

    对于居中的列表,它们会发生一些变化:

    +-----+---+---------+
    |  A  | B |    C    |
    +-----+---+---------+
    ^  ^           ^    ^
    a  c           d    b
    

    为了使滚动正确,我们需要将<ul> 的宽度从 A->B 更改为 C->D。由于它的宽度是由其子宽度动态计算的,因此我们需要更改子宽度。

    我们可以看到只有第一个和最后一个孩子是要改变的。由于文本定义了每个孩子的宽度,我们无法更改宽度属性,但我们可以更容易地将一些定义的值除以 2:字体大小、填充。

    li {
      font-size: 12px;
      padding: 0 50px;
    }
    
    li:first-child, li-last-child {
      font-size: 6px;
      padding: 0 25px;
    }
    

    现在列表可能看起来更像

    +---+---+-----+
    | a | B |  c  |
    +---+---+-----+
    ^  ^       ^  ^
    a  c       d  b
    

    但是问题是文本和填充现在更小了。我们可以做的是将真正的按钮代理到 :after 中,只需向 li 添加一个文本属性以提供 content 属性。

    <li text='A'>A</li>
    <li text='B'>B</li>
    <li text='C'>C</li>
    

    在 DOM 中,我们可以编写那种 CSS 来创建看起来像真实按钮的假按钮(更不用说,隐藏真实按钮......)

    li {
      position: relative;
      background: transparent;
      color: transparent;
    }
    
    li:after {
      display: block;
      overflow: hidden;
      position: absolute;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
      content: attr(text);
      color: #000;
    }
    

    快到了,快到了……

    第一个和最后一个孩子已经被改变了,所以他们的伪孩子也被改变了......副作用是宽度将被计算为 6px 字体大小。所以我们需要将宽度设置回所需的两倍,并重新设置字体大小以防止继承。

    li:first-child:after, #d li:last-child:after {
      font-size: 12px;
      width: 200%;
    }
    

    最后(耶),我们将第一个元素填充到其宽度的一半,以防止与第二个元素发生冲突。

    li:first-child:after {
      left: -100%;
    } 
    

    我们也可以使用transform: translateX(-50%);,但我们已经在处理绝对值,因此无需对其应用其他计算层。

    希望对某人有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-07
      • 2011-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-31
      • 1970-01-01
      • 2012-02-27
      相关资源
      最近更新 更多