公认的解决方案非常有效,但国际海事组织缺乏对其为何有效的解释。下面的例子被归结为基础,并将重要的CSS从无关的样式CSS中分离出来。另外,我还详细解释了CSS定位的工作原理。
TLDR;如果你只想要代码,向下滚动到结果。
这个问题
有两个独立的兄弟元素,目标是定位第二个元素(id为infoi),因此它出现在前一个元素(类为navi的元素)中。HTML结构不可更改。
建议的解决方案
为了达到预期的结果,我们将移动或定位第二个元素,我们将其称为#infoi,以便它出现在第一个元素中,我们将其称为.navi。具体来说,我们希望#infoi被定位在.navi的右上角。
CSS岗位要求知识
CSS有几个定位元素的属性。默认情况下,所有元素都是position: static。这意味着元素将根据其在HTML结构中的顺序进行定位,几乎没有例外。
其他位置值是相对的、绝对的、粘滞的和固定的。通过将元素的位置设置为其他值之一,现在可以使用以下四个属性的组合来定位元素:
前
正确的
底
左
换句话说,通过设置position: absolute,我们可以添加top: 100px来将元素定位到距离页面顶部100像素的位置。相反,如果我们设置bottom: 100px,元素将位于距离页面底部100像素处。
这是许多CSS新手迷失的地方——位置:绝对有一个参照系。在上面的例子中,参考框架是body元素。Position: absolute with top: 100px表示该元素位于距离body元素顶部100像素处。
位置参考系或位置上下文可以通过将父元素的位置设置为position: static以外的任何值来更改。也就是说,我们可以通过给出一个父元素来创建一个新的位置上下文:
位置:相对;
位置:绝对的;
位置:粘性;
位置:固定;
例如,如果一个<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>元素。因为在HTML结构中<div>Top</div>在<div>Bottom</div>之后,所以它有更高的堆叠顺序。
div {
位置:绝对的;
宽度:50%;
高度:50%;
}
#{底部
上图:0;
左:0;
背景颜色:蓝色;
}
#{顶部
上图:25%;
左:25%;
背景颜色:红色;
}
底< div id = "底" > < / div >
< div id = "顶级" >顶部< / div >
可以使用z-index或order属性在CSS中更改堆叠顺序。
在这个问题中,我们可以忽略元素的堆叠顺序,因为元素的自然HTML结构意味着我们想要出现在顶部的元素位于其他元素之后。
所以,回到手头的问题——我们将使用位置上下文来解决这个问题。
解决方案
如上所述,我们的目标是定位#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一个位置:absolute,允许我们在.wrapper中绝对放置#infoi。
然后添加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元素位于最右边。我使用了verbose网格属性使其尽可能清晰。
: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的情况下,这意味着我们不能添加包装器元素,我们仍然可以达到预期的效果。
在#infoi元素上,我们不再使用position: absolute,而是使用position: relative。这允许我们将#infoi元素从.navi元素下方的默认位置重新定位。对于position: relative,我们可以使用一个负的顶部值将它从默认位置向上移动,并使用left: calc(100% - 52px)将左侧值100%减去几个像素,将它放置在右侧附近。
/*
* 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>