我的JavaScript代码有问题。我正在实现一个纸牌游戏,我点击一个按钮,13张牌应该每隔一段时间出现。
$("button").click(function() {
let i = 0;
setInterval(function() {
if(i == 4) clearInterval();
$(".block").eq(i).css({visibility:"visible"});
$(".block").eq(i).html("TEXT" + i);
i++;
},100);
});
.block {
display: inline-block;
width: 100px;
height: 140px;
border: 2px solid;
visibility: hidden;
}
button {
position: absolute;
top: 170px;
left: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<body>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<button id="button">Generate!</button>
</body>
</html>
如上所述,我使用setInterval()
函数以100ms的间隔显示它们,所有div都按照我的指示执行,但它们首先出现在我想要的位置以下。我如何才能使它们直接出现在正确的位置?
提前感谢!
将vertical-align: top;
添加到内联元素
$("button").click(function() {
let i = 0;
setInterval(function() {
if(i == 4) clearInterval();
$(".block").eq(i).css({visibility:"visible"});
$(".block").eq(i).html("TEXT" + i);
i++;
},100);
});
.block {
display: inline-block;
width: 100px;
height: 140px;
border: 2px solid;
visibility: hidden;
vertical-align: top;
}
button {
position: absolute;
top: 170px;
left: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<body>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<button id="button">Generate!</button>
</body>
</html>
将块设置为display: none
,然后添加display: inline-block
是解决问题的一种方法,但不能解决问题本身。
主要问题是block
类上的vertical-align
属性集。默认情况下,此选项设置为baseline
。在单击按钮之前,所有div都排成一行,不可见,其基线设置在div的底部。然而,当单击按钮时,不仅块变得可见,而且更重要的是,您在div中添加了一些文本。这会更改基线,使其成为div中文本的底部。但是,由于vertical-align: baseline
,行中所有div的基线都试图对齐。有文本的可见div的基线必须与没有文本的不可见div的基准对齐。但他们的基线现在不同了,所以他们都能在基线上坐在一条直线上的唯一方法是按下带文本的div。
我简化了你的片段,让你明白我的意思。我已经使div可见,删除了按钮,而是在html中手动向div添加了一些文本。正如您所看到的,对于有文本的div,文本的底部与没有文本的div的底部对齐。
body {
background: white;
}
.block {
display: inline-block;
width: 100px;
height: 140px;
border: 2px solid;
}
<html>
<body>
<div class="block">TEXT</div>
<div class="block">TEXT</div>
<div class="block"></div>
<div class="block">TEXT</div>
</body>
</html>
一开始将块更改为display: none
,然后逐个显示它们之所以有效,是因为在这种情况下,DOM中永远不会同时出现无文本的div和带文本的div,因此永远不会出现基线不匹配的情况。div进入DOM时带有文本,因此它们的基线总是匹配的。然而,这并不能完全解决问题。例如,如果div中的文本长度不同,则多行文本的底部将与单行文本的底部匹配,从而再次导致错位。
示例:
body {
background: white;
}
.block {
display: inline-block;
width: 100px;
height: 140px;
border: 2px solid;
}
<html>
<body>
<div class="block">text</div>
<div class="block">text</div>
<div class="block">very long text which takes up more than one line</div>
<div class="block">text</div>
</body>
</html>
因此,正确的解决方案是将vertical-align: top
添加到block
类中,以确保我们的对齐不会随着基线的变化而到处跳跃。
您可以将.block
元素设置为display: none;
而不是visibility: hidden;
,并将脚本更改为:
$("button").click(function() {
let i = 0;
setInterval(function() {
if(i == 4) clearInterval();
$(".block").eq(i).css({display:"inline-block"});
$(".block").eq(i).html("TEXT" + i);
i++;
},100);
});
Fiddle
您可以在.block元素周围放置一个包装器div。
<html>
<body>
<div class="container">
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
</div>
<button id="button">Generate!</button>
</body>
</html>
然后是CSS:
.container {
display: flex;
}
.block {
/* display: inline-block; */
width: 100px;
height: 140px;
border: 2px solid;
visibility: hidden;
margin-left: 15px;
}
我为所有.block元素添加了一个左边空白,但您当然可以使用flex显示器或任何您想要的方式来设置它们。
这是一把正在工作的小提琴。
您可以将高度设置为0
,然后在间隔函数中进行设置。
$("button").click(function() {
let i = 0;
setInterval(function() {
if(i == 4) clearInterval();
$(".block").eq(i).css({visibility:"visible", height: "140px"});
$(".block").eq(i).html("TEXT" + i);
i++;
},100);
});
使用此css:
.block {
display: inline-block;
width: 100px;
height: 0;
border: 2px solid;
visibility: hidden;
}
button {
position: absolute;
top: 170px;
left: 50px;
}