水平滚动列表完全居中,动态宽度项目
horizontal scrollable list fully centered with dynamic width items
我正在尝试使水平列表居中,其项目也相对于主要父项(window 或正文)居中;因为我不知道我将在该列表中生成什么类型和多少项目,所以我需要这些项目的宽度是动态的并且列表是可滚动的,这样我就可以浏览所有这些项目。
到目前为止,我的尝试都很好,我得到了:一个居中的列表,其中包含动态宽度的非居中项目;以及具有固定宽度项目的完全居中的可滚动列表。
核心思想基本上是通过使用实现的:
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%)
稍微改变一下:因为我不希望我的列表在滚动结束时有额外的 space ,我将最后一项从流程中删除,方法是将其绝对定位在末尾;这样,<ul>
宽度看起来就像是项目宽度减去一项的总和。
ul {
position: relative;
margin: 0 50%;
}
li {
display: inline-block;
width: some_number;
transform: translateX(-50%);
}
li:last-child {
position: absolute;
left: 100%;
}
但是如何在不设置宽度的情况下保持这种状态对我来说是个谜。
有什么想法吗?
这是我的 fiddle,在 CSS 部分有一些评论:https://jsfiddle.net/11gkrju0/
我希望不要为此使用javascript,因为这只是样式问题,但弄乱dom是一个完全可行的选择。
感谢大家的阅读,
好吧,这有点棘手。已解决的 fiddle 附有评论,我也将在此处进行描述。 https://jsfiddle.net/11gkrju0/7/
首先要注意的是,我在 <li>
中添加了一个 vertical-align: top;
以确保在某些点上没有垂直间隙。
然后.
非居中列表的边界很容易捕捉:
+-----+---+---------+
| A | B | C |
+-----+---+---------+
^ ^
a b
对于居中列表,它们会稍微改变一下:
+-----+---+---------+
| A | B | C |
+-----+---+---------+
^ ^ ^ ^
a c d b
为了向右滚动,我们需要将 <ul>
的宽度从 A->B 更改为 C->D。由于它的宽度是由它的 children 宽度动态计算的,我们需要改变 children.
我们可以看到只有第一个和最后一个children是要改变的。由于文本定义了每个 children 的宽度,我们不能更改宽度 属性,但我们可以更容易地除以 2 一些定义的值:font-size,padding.
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;
}
快到了,快到...
第一个和最后一个 children 已更改,因此它们的 pseudo-child 也被更改...副作用是宽度将计算为 6px font-size。所以我们需要将宽度设置回所需的两倍,并重置 font-size 以防止继承。
li:first-child:after, #d li:last-child:after {
font-size: 12px;
width: 200%;
}
最后(是的),我们将第一个元素填充到其宽度的一半,以防止与第二个元素发生冲突。
li:first-child:after {
left: -100%;
}
我们也可以使用 transform: translateX(-50%);
,但我们已经在处理绝对值,因此无需对其应用其他计算层。
希望对某人有所帮助。
我正在尝试使水平列表居中,其项目也相对于主要父项(window 或正文)居中;因为我不知道我将在该列表中生成什么类型和多少项目,所以我需要这些项目的宽度是动态的并且列表是可滚动的,这样我就可以浏览所有这些项目。
到目前为止,我的尝试都很好,我得到了:一个居中的列表,其中包含动态宽度的非居中项目;以及具有固定宽度项目的完全居中的可滚动列表。
核心思想基本上是通过使用实现的:
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%)
稍微改变一下:因为我不希望我的列表在滚动结束时有额外的 space ,我将最后一项从流程中删除,方法是将其绝对定位在末尾;这样,<ul>
宽度看起来就像是项目宽度减去一项的总和。
ul {
position: relative;
margin: 0 50%;
}
li {
display: inline-block;
width: some_number;
transform: translateX(-50%);
}
li:last-child {
position: absolute;
left: 100%;
}
但是如何在不设置宽度的情况下保持这种状态对我来说是个谜。
有什么想法吗?
这是我的 fiddle,在 CSS 部分有一些评论:https://jsfiddle.net/11gkrju0/
我希望不要为此使用javascript,因为这只是样式问题,但弄乱dom是一个完全可行的选择。
感谢大家的阅读,
好吧,这有点棘手。已解决的 fiddle 附有评论,我也将在此处进行描述。 https://jsfiddle.net/11gkrju0/7/
首先要注意的是,我在 <li>
中添加了一个 vertical-align: top;
以确保在某些点上没有垂直间隙。
然后.
非居中列表的边界很容易捕捉:
+-----+---+---------+
| A | B | C |
+-----+---+---------+
^ ^
a b
对于居中列表,它们会稍微改变一下:
+-----+---+---------+
| A | B | C |
+-----+---+---------+
^ ^ ^ ^
a c d b
为了向右滚动,我们需要将 <ul>
的宽度从 A->B 更改为 C->D。由于它的宽度是由它的 children 宽度动态计算的,我们需要改变 children.
我们可以看到只有第一个和最后一个children是要改变的。由于文本定义了每个 children 的宽度,我们不能更改宽度 属性,但我们可以更容易地除以 2 一些定义的值:font-size,padding.
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;
}
快到了,快到...
第一个和最后一个 children 已更改,因此它们的 pseudo-child 也被更改...副作用是宽度将计算为 6px font-size。所以我们需要将宽度设置回所需的两倍,并重置 font-size 以防止继承。
li:first-child:after, #d li:last-child:after {
font-size: 12px;
width: 200%;
}
最后(是的),我们将第一个元素填充到其宽度的一半,以防止与第二个元素发生冲突。
li:first-child:after {
left: -100%;
}
我们也可以使用 transform: translateX(-50%);
,但我们已经在处理绝对值,因此无需对其应用其他计算层。
希望对某人有所帮助。