我的网页布局使用了flexbox。我正在尝试创建一个选项卡内容组件,该组件将自动调整其选项卡内容的最大值。理想情况下,我也喜欢在各州之间褪色。我正在尝试使用position: absolute
将myTabContents1
和myTabContents2
叠加在一起。然后,我使用visibility
和opacity
选择可见的那个。
所以DOM基本上看起来像这样(为了简单起见,我只显示标签页的内容,而不是用于在它们之间切换的实际用户控件):
<div class='tabContentsList'>
<div class='tabContentsItem'>
Contents of first tab
</div>
<div class='tabContentsItem activeTab'>
Contents of second tab.
</div>
</div>
我的css是:
.tabContentsList {
width: 100%;
height: 100%;
position: relative;
display: flex;
flex-direction: column;
}
.tabContentsItem {
display: flex;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
visibility: hidden;
opacity: 0;
transition: visibility 0.3s linear, opacity 0.3s linear;
}
.tabContentsItem.activeTab {
opacity: 1;
visibility: visible;
}
切换标签时,这会正确显示淡化效果。但是,tabContentsList
元素的大小不能包含tabContentsItem
元素 - 它基本上将它们视为零大小,因此最终会溢出它们的边界。我已尝试将right: 0
替换为width: 100%
等,但这没有用。如果你另一方面删除了position: absolute
,那么容器会扩展以容纳两个标签的内容,但定位显然是不正确的 - 为隐形标签留下了一个空白区域。显然,flexbox
和position: absolute
之间存在已知冲突。
那么有另一种方法来实现这一目标吗?例如,是否有另一种方法来覆盖不使用position: absolute
且Flexbox会尊重的两个选项卡内容?如果它可以工作,这似乎是一个有用的工具。
谢谢你的任何想法。
答案 0 :(得分:1)
一般而言,由于绝对定位会使元素无法流动,因此很难根据内容创建适当大小的解决方案,并且很可能需要使用脚本。
另一种选择是使用 transform
代替定位,可以使标签内容元素的大小相等。
另一种选择是使用负边距代替,对于定位,可以使标签内容元素的大小相等。
此处设置display: flex
/ tabs
上的tabscontent
,默认为align-items
的{{1}}会保持同等效率。
stretch
将告诉flex: 0 0 100%
填充其父级宽度,然后使用 负边距,我们可以撤回tabcont1/2/3
translateX()
在位置。
注意,由于转换后的元素上的tabcont2/3
在动画期间来回移动文本,在Chrome中比其他浏览器更明显,我转而使用负边距。当我找到避免这种情况的方法时,我会使用这两种解决方案进行更新。
Stack snippet
transition
&#13;
.tabs-wrapper {
width: 80%;
margin: 0 auto;
}
.tabs-wrapper input {
display: none;
}
.tabs-wrapper > div {
display: flex;
}
.tabs-wrapper .tabs > label {
padding: 5px;
border: 1px solid lightgray;
box-sizing: border-box;
cursor: pointer;
}
.tabs-wrapper .tabscontent {
padding: 5px;
border: 1px solid lightgray;
}
.tabs-wrapper .tabscontent > div {
flex: 0 0 100%;
opacity: 0;
transition: opacity .5s;
}
/*.tabs-wrapper .tabscontent > div:nth-child(2) {
transform: translateX(-100%);
}
.tabs-wrapper .tabscontent > div:nth-child(3) {
transform: translateX(-200%);
}*/
.tabs-wrapper .tabscontent > div:nth-child(n+2) {
margin-left: -100%;
}
.tabs-wrapper input:nth-child(1):checked ~ .tabs label:nth-child(1),
.tabs-wrapper input:nth-child(2):checked ~ .tabs label:nth-child(2),
.tabs-wrapper input:nth-child(3):checked ~ .tabs label:nth-child(3) {
background: lightblue;
}
.tabs-wrapper input:nth-child(1):checked ~ .tabscontent > div:nth-child(1),
.tabs-wrapper input:nth-child(2):checked ~ .tabscontent > div:nth-child(2),
.tabs-wrapper input:nth-child(3):checked ~ .tabscontent > div:nth-child(3) {
opacity: 1;
}
&#13;
如果有人无法使用Flexbox,则您不需要
<div class="tabs-wrapper">
<input id="tab1" type="radio" name="tab" checked>
<input id="tab2" type="radio" name="tab">
<input id="tab3" type="radio" name="tab">
<div class="tabs">
<label for="tab1">Tab 1</label>
<label for="tab2">Tab 2, which is longer</label>
<label for="tab3">Tab 3</label>
</div>
<div class="tabscontent">
<div class="tabcont1">Content 1</div>
<div class="tabcont2">Content 2,<br>which is higher<br>than 1 and 3</div>
<div class="tabcont1">Content 3</div>
</div>
</div>
&#13;
.tabs-wrapper {
width: 80%;
margin: 0 auto;
overflow: hidden;
}
.tabs-wrapper input {
display: none;
}
.tabs-wrapper .tabs > label {
display: inline-block;
padding: 5px;
border: 1px solid lightgray;
box-sizing: border-box;
vertical-align: top;
cursor: pointer;
}
.tabs-wrapper .tabscontent {
padding: 5px;
border: 1px solid lightgray;
white-space: nowrap;
}
.tabs-wrapper .tabscontent > div {
display: inline-block;
width: 100%;
opacity: 0;
transition: opacity .5s;
white-space: normal;
vertical-align: top;
}
/*.tabs-wrapper .tabscontent > div:nth-child(2) {
transform: translateX(-100%);
}
.tabs-wrapper .tabscontent > div:nth-child(3) {
transform: translateX(-200%);
}*/
.tabs-wrapper .tabscontent > div:nth-child(n+2) {
margin-left: -100%;
}
.tabs-wrapper input:nth-child(1):checked ~ .tabs label:nth-child(1),
.tabs-wrapper input:nth-child(2):checked ~ .tabs label:nth-child(2),
.tabs-wrapper input:nth-child(3):checked ~ .tabs label:nth-child(3) {
background: lightblue;
}
.tabs-wrapper input:nth-child(1):checked ~ .tabscontent > div:nth-child(1),
.tabs-wrapper input:nth-child(2):checked ~ .tabscontent > div:nth-child(2),
.tabs-wrapper input:nth-child(3):checked ~ .tabscontent > div:nth-child(3) {
opacity: 1;
}
&#13;
更新
以下是更新的Flexbox版本,其中<div class="tabs-wrapper">
<input id="tab1" type="radio" name="tab" checked>
<input id="tab2" type="radio" name="tab">
<input id="tab3" type="radio" name="tab">
<div class="tabs">
<label for="tab1">Tab 1</label><!--
--><label for="tab2">Tab 2, which is longer</label><!--
--><label for="tab3">Tab 3</label>
</div>
<div class="tabscontent">
<div class="tabcont1">Content 1</div><!--
--><div class="tabcont2">Content 2,<br>which is higher<br>than 1 and 3</div><!--
--><div class="tabcont1">Content 3</div>
</div>
</div>
显示为弹性列容器,并且container
设置为align-items
,它实际上是基于flex-start
的大小关于内容。
每个项目仍然会比实际内容宽一些,并且需要具有相同的宽度,以便可以使用负边距(或tabcont1/2/3
)将它们左对齐定位。
Flexbox用于调整大小的逻辑来自此帖子Flexbox in IE doesn't set item widths correctly
因此,最终要使每个项目在视觉上正确呈现,并且额外的包装器(此处为translate
)用于填充和边框。
为了能够对此进行更优化,因为需要脚本。
span
&#13;
.tabs-wrapper {
display: inline-flex;
flex-direction: column;
align-items: flex-start;
}
.tabs-wrapper input {
display: none;
}
.tabs-wrapper > div {
display: flex;
}
.tabs-wrapper .tabs > label {
padding: 5px;
border: 1px solid lightgray;
box-sizing: border-box;
cursor: pointer;
}
.tabs-wrapper .tabscontent {
}
.tabs-wrapper .tabscontent > div {
width: 100%;
opacity: 0;
transition: opacity .5s;
display: flex;
}
.tabs-wrapper .tabscontent > div > span {
display: inline-block;
padding: 5px;
border: 1px solid lightgray;
}
/*.tabs-wrapper .tabscontent > div:nth-child(2) {
transform: translateX(-100%);
}
.tabs-wrapper .tabscontent > div:nth-child(3) {
transform: translateX(-200%);
}*/
.tabs-wrapper .tabscontent > div:nth-child(n+2) {
margin-left: -100%;
}
.tabs-wrapper input:nth-child(1):checked ~ .tabs label:nth-child(1),
.tabs-wrapper input:nth-child(2):checked ~ .tabs label:nth-child(2),
.tabs-wrapper input:nth-child(3):checked ~ .tabs label:nth-child(3) {
background: lightblue;
}
.tabs-wrapper input:nth-child(1):checked ~ .tabscontent > div:nth-child(1),
.tabs-wrapper input:nth-child(2):checked ~ .tabscontent > div:nth-child(2),
.tabs-wrapper input:nth-child(3):checked ~ .tabscontent > div:nth-child(3) {
opacity: 1;
}
&#13;
答案 1 :(得分:1)
如果您考虑display:grid
而不是flex,您可以将每个标签堆放在同一个位置,并根据最宽和最高的尺寸对它们进行调整:
#tabsthing {
display: grid;
grid-template-areas: "tab . ";
grid-template-columns: auto 1fr;
}
a {
grid-area: tab;
}
/* make up for demo purpose */
a:hover {
opacity: 0;
}
a {
border: solid;
padding: 1em;
background: turquoise;
transition: 1s;
opacity: 0.5;
}
a+a {
background: tomato;
text-align: right;
}
a:last-of-type {
background: yellow;
}
&#13;
<div id="tabsthing">
<a href="#one">One of three<br/>next line</a>
<a href="#two">second of three</a>
<a href="#three"> third of a test about lenght</a>
</div>
&#13;
https://codepen.io/gc-nomade/pen/pWWQVN
免责声明:这可能是一个专门的javascript工作,毕竟是可靠的。