公认的解决方案效果很好,但 IMO 没有解释它为什么起作用。下面的示例归结为基础知识,并将重要的 CSS 与不相关的样式 CSS 分开。作为奖励,我还详细解释了 CSS 定位的工作原理。
TLDR;如果您只想要代码,请向下滚动到结果。
问题
有两个独立的兄弟元素,目标是定位第二个元素(infoi 的 id),使其出现在前一个元素中(@987654324 的 class @)。 HTML 结构无法更改。
建议的解决方案
为了达到预期的效果,我们将移动或定位第二个元素,我们将其称为#infoi,使其出现在第一个元素中,我们将其称为.navi。具体来说,我们希望#infoi 位于.navi 的右上角。
CSS职位所需知识
CSS 有几个用于定位元素的属性。默认情况下,所有元素都是position: static。这意味着元素将根据其在 HTML 结构中的顺序进行定位,几乎没有例外。
其他position 值为relative、absolute、sticky 和fixed。通过将元素的 position 设置为这些其他值之一,现在可以使用以下四个属性的组合来定位元素:
换句话说,通过设置position: absolute,我们可以添加top: 100px,将元素定位在距页面顶部100像素的位置。相反,如果我们设置bottom: 100px,则元素将位于距页面底部 100 像素处。
这是许多 CSS 新手迷路的地方 - position: absolute 有一个参考框架。在上面的示例中,参考框架是body 元素。 position: absolute 和 top: 100px 表示元素位于距离 body 元素顶部 100 像素处。
可以通过将父元素的position 设置为position: static以外的任何值来更改位置参考框架或位置上下文。也就是说,我们可以通过给父元素创建一个新的位置上下文:
position: relative;
position: absolute;
position: sticky;
position: fixed;
例如,如果<div class="parent"> 元素被指定为position: relative,则任何子元素都使用<div class="parent"> 作为其位置上下文。如果为子元素指定了position: absolute 和top: 100px,则该元素将位于距<div class="parent"> 元素顶部100 像素处,因为<div class="parent"> 现在是位置上下文。
另一个需要注意的因素是堆叠顺序 - 或者元素在 z 方向上的堆叠方式。这里必须知道的是元素的堆栈顺序,默认情况下,由它们在 HTML 结构中的顺序相反的顺序定义。考虑以下示例:
<body>
<div>Bottom</div>
<div>Top</div>
</body>
在本例中,如果两个<div> 元素位于页面上的同一位置,则<div>Top</div> 元素将覆盖<div>Bottom</div> 元素。由于<div>Top</div> 在 HTML 结构中位于 <div>Bottom</div> 之后,因此它具有更高的堆叠顺序。
div {
position: absolute;
width: 50%;
height: 50%;
}
#bottom {
top: 0;
left: 0;
background-color: blue;
}
#top {
top: 25%;
left: 25%;
background-color: red;
}
<div id="bottom">Bottom</div>
<div id="top">Top</div>
可以使用 z-index 或 order 属性通过 CSS 更改堆叠顺序。
我们可以忽略此问题中的堆叠顺序,因为元素的自然 HTML 结构意味着我们希望出现在 top 上的元素位于另一个元素之后。
所以,回到手头的问题 - 我们将使用位置上下文来解决这个问题。
解决方案
如上所述,我们的目标是定位#infoi 元素,使其出现在.navi 元素中。为此,我们将 .navi 和 #infoi 元素包装在一个新元素 <div class="wrapper"> 中,这样我们就可以创建一个新的位置上下文。
<div class="wrapper">
<div class="navi"></div>
<div id="infoi"></div>
</div>
然后通过给.wrapper 一个position: relative 创建一个新的位置上下文。
.wrapper {
position: relative;
}
有了这个新的位置上下文,我们可以在.wrapper 中定位#infoi。首先,给#infoi一个position: absolute,允许我们将#infoi绝对定位在.wrapper中。
然后添加top: 0 和right: 0 将#infoi 元素定位在右上角。请记住,因为#infoi 元素使用.wrapper 作为其位置上下文,所以它将位于.wrapper 元素的右上角。
#infoi {
position: absolute;
top: 0;
right: 0;
}
因为.wrapper 只是.navi 的容器,所以将#infoi 定位在.wrapper 的右上角会产生定位在.navi 右上角的效果。
我们找到了,#infoi 现在似乎位于.navi 的右上角。
结果
下面的示例归结为基础,并包含一些最小的样式。
/*
* position: relative gives a new position context
*/
.wrapper {
position: relative;
}
/*
* The .navi properties are for styling only
* These properties can be changed or removed
*/
.navi {
background-color: #eaeaea;
height: 40px;
}
/*
* Position the #infoi element in the top-right
* of the .wrapper element
*/
#infoi {
position: absolute;
top: 0;
right: 0;
/*
* Styling only, the below can be changed or removed
* depending on your use case
*/
height: 20px;
padding: 10px 10px;
}
<div class="wrapper">
<div class="navi"></div>
<div id="infoi">
<img src="http://via.placeholder.com/32x20/000000/ffffff?text=?" height="20" width="32"/>
</div>
</div>
另一种(网格)解决方案
这是使用 CSS Grid 将 .navi 元素与最右侧的 #infoi 元素定位的替代解决方案。我使用了详细的grid 属性使其尽可能清晰。
:root {
--columns: 12;
}
/*
* Setup the wrapper as a Grid element, with 12 columns, 1 row
*/
.wrapper {
display: grid;
grid-template-columns: repeat(var(--columns), 1fr);
grid-template-rows: 40px;
}
/*
* Position the .navi element to span all columns
*/
.navi {
grid-column-start: 1;
grid-column-end: span var(--columns);
grid-row-start: 1;
grid-row-end: 2;
/*
* Styling only, the below can be changed or removed
* depending on your use case
*/
background-color: #eaeaea;
}
/*
* Position the #infoi element in the last column, and center it
*/
#infoi {
grid-column-start: var(--columns);
grid-column-end: span 1;
grid-row-start: 1;
place-self: center;
}
<div class="wrapper">
<div class="navi"></div>
<div id="infoi">
<img src="http://via.placeholder.com/32x20/000000/ffffff?text=?" height="20" width="32"/>
</div>
</div>
另一种(无包装)解决方案
在我们无法编辑任何 HTML 的情况下,意味着我们无法添加包装元素,我们仍然可以达到预期的效果。
我们将使用position: relative,而不是在#infoi 元素上使用position: absolute。这允许我们将#infoi 元素从.navi 元素下方的默认位置重新定位。使用position: relative,我们可以使用负值top 将其从默认位置向上移动,使用left 值100% 减去几个像素,使用left: calc(100% - 52px),将其定位在右侧附近.
/*
* The .navi properties are for styling only
* These properties can be changed or removed
*/
.navi {
background-color: #eaeaea;
height: 40px;
width: 100%;
}
/*
* Position the #infoi element in the top-right
* of the .wrapper element
*/
#infoi {
position: relative;
display: inline-block;
top: -40px;
left: calc(100% - 52px);
/*
* Styling only, the below can be changed or removed
* depending on your use case
*/
height: 20px;
padding: 10px 10px;
}
<div class="navi"></div>
<div id="infoi">
<img src="http://via.placeholder.com/32x20/000000/ffffff?text=?" height="20" width="32"/>
</div>