根据位置进行自适应文本对齐

时间:2018-09-28 13:41:41

标签: html css

我认为答案是“否”,但是,在做出更大的改变之前,我想确保自己没有错过任何事情。

是否有一种仅通过CSS的方法,可以根据元素及其子元素的方向是更偏向屏幕的左侧还是右侧来更改其对正?

没有直接的属性,但是我正在查看是否错过了一些可能涉及伪选择器或元素的类似hack的方法。

当前困境的证明:

我有一个<ul>导航栏,提供了<a>链接和一些嵌套的<ul>容器的混合物,用于悬停菜单。非常标准,可以在更大的屏幕上正常工作:

enter image description here

如果可用的屏幕空间较少,则导航将按预期换行到下一行。这是理想的结果。但是,有时下拉菜单可以在屏幕外被截断,这不是很理想:

enter image description here

与其为移动设备提供截然不同的样式(我的后备计划是通过postion: fixed在较小的屏幕上以类似于对话框的形式显示下拉菜单,而不是像以前那样position: absolute现在),我可以通过让元素意识到自己在屏幕外的冒险以及对text-align: right的需求以及可能调整其绝对位置以将其锚定在父<li>右边的情况来解决自己的情况比现在的左侧要高:

enter image description here

我可以通过javascript来管理此问题,但是已经发生了足够多的侦听器事件,并且希望提供一种避免使用javascript的更优雅的响应。如果没有css-only方法,我可能会使用固定位置替代方案作为计划b。

说明:

虽然我原本希望使用媒体查询来解决移动设备上的这种困境,但我意识到,尽管对我来说,这只出现在较小的屏幕上,但这并不是我理所当然的事情。

例如,导航项的数量将来可能会增加,并且在任何屏幕尺寸下都可能出现这种情况。它只需要一个下拉菜单位于屏幕右侧。

我也不能保证我尚未测试的设备不会以我没有想到的大小复制该问题。

我的意思是,我没有找到一种依靠屏幕尺寸媒体查询的方法。我认为我的解决方案(如果有的话)需要响应元素在屏幕上的位置-这就是为什么我认为对于非JavaScript解决方案我可能不走运。

第二:假定内容是动态的,并且像任何有能力的页面一样,元素应动态更改属性以适应此情况(例如导航项的顺序,计数,宽度等)。我应该将任何在此方面寻求更好警告的人推荐给原始问题:是否有一种方法,仅通过CSS可以根据元素和其子元素的朝向是更偏向于其左侧还是右侧来改变其对齐方式屏幕?

示例代码:

根据要求,这里是示例代码。我认为在这种情况下将它包括在内不是一个好主意(尽管了解它在大多数问题中的重要性),因为它减损了与我的特定代码无关的问题,而与质疑css动态修改在任何情况下都基于屏幕位置或对屏幕边缘的了解来确定属性,因此我倾向于说明问题。

该代码是我自己的简化版本,但是几乎可以使用标准,熟悉的<ul>导航菜单的任何变体来提问该问题,该菜单通过CSS中的:hover提供下拉菜单。 / p>

考虑到这一点,如果您试图通过研究我的代码来解决问题,那么我可能很难描述我的困境。我相信我对CSS目前可以应用的范围非常精通,并且相信答案是“没有javascript就不可能”,但只是确保我没有错过用于动态更改元素属性的聪明的解决方法/技巧。通过基于屏幕位置的CSS(很抱歉重复这个问题-我只想确保能理解它,并附上一些评论)。谢谢。

<ul class="nav nav__container">

    <li><a class='nav nav__item' href="#">Standard Link</a></li>
    <li><a class='nav nav__item' href="#">Standard Link</a></li>
    <li><a class='nav nav__item' href="#">Standard Link</a></li>
    <li><a class='nav nav__item' href="#">Standard Link</a></li>
    <li class='nav nav__item nav__item--dropdown'><li><a href="#">Dropdown Label</a></li>
        <ul class='nav nav__dropdown'>
            <li><a class='nav nav__item nav__item--dditem' href="#">Dropdown Link</a></li>
            <li><a class='nav nav__item nav__item--dditem' href="#">Dropdown Link</a></li>
            <li><a class='nav nav__item nav__item--dditem' href="#">Dropdown Link</a></li>
        </ul>
    </li>

</ul>

4 个答案:

答案 0 :(得分:4)

确实存在一个仅CSS的解决方案,其效果与您在问题所附图像中呈现的完全一样。但是,这可能不是一个真正完整的答案,因为它取决于一个关键因素-所有顶级菜单项的宽度都相同。现在,附件图像中显示的是 情况,但实际执行情况可能并非如此。


使用CSS3 nth-child选择器和n变量,您可以定位第3个或第4个顶层菜单项。可以轻松设置目标项目的样式,使其下拉菜单正确对齐。因此,对于在单个屏幕上进行硬编码的解决方案,您将计算一行中顶层菜单项的数量,并将其设置为n乘数。例如,如果您的菜单在6个项目后进行换行,则要设置每行的最后一个项目的样式,应设置以下内容:

.top-level-item:nth-child(6n) > .dropdown-container > .sub-item {
    float: right;
    clear: right;
}

或者您的实际实现需要设置一个右对齐菜单的样式。

当然,这取决于所有具有相同宽度的菜单项。如果菜单有多于2行,并且菜单项的宽度不同,则每行中元素的数量可能会变化,在这种情况下,nth-child选择器不一定会以每行的末尾子对象为目标。

现在要使此功能适用于任何屏幕尺寸,如果所有顶级项目都具有相同的固定宽度,那么我们需要找出每行有多少个项目,而与窗口的宽度无关。遗憾的是,calc()对于此应用程序来说太受限制了。但是,如果最上面的项目具有固定的宽度,并且我们知道该宽度是多少,我们可以针对每种情况使用一系列@media语句。

例如,假设边距和宽度在一起,则每个顶级项目的宽度均为230px。这意味着,如果窗口的宽度小于230 * 3 = 690px,则每行中将有2个项目。如果窗口的宽度小于230 * 4 = 920px且大于690px,则每行将有3个项目。依此类推,直到您认为需要的最大窗口大小。使用上面的nth-child示例,针对每个行大小的一系列媒体查询如下所示:

@media (max-width: 690px) {
    /* less than 3 items per row */
    .top-level-item:nth-child(2n) > .dropdown-container > .sub-item {
        float: right;
        clear: right;
    }
}
@media (max-width: 920px) and (min-width: 691px) {
    /* less than 4 items per row */
    .top-level-item:nth-child(3n) > .dropdown-container > .sub-item {
        float: right;
        clear: right;
    }
}
@media (max-width: 1150px) and (min-width: 921px) {
    /* less than 5 items per row */
    .top-level-item:nth-child(4n) > .dropdown-container > .sub-item {
        float: right;
        clear: right;
    }
}
...
/* and so on */

显示该实现方式的笔位于https://codepen.io/jla-/pen/GYJQMq。请注意,只有单击JavaScript才能在单击下拉菜单时对其进行切换。


对于具有可变宽度的顶级菜单项,或者如果它们具有相同的宽度,但是您不知道它的值,我认为当前的CSS没有足够的功能来执行您想要的操作。理想情况下,您可以执行.top-level-item:nth-child(calc((100vw/--itemwidth)-(100vw%--itemwidth))之类的操作来连续获取项目数,但是我认为CSS距离这种功能还很遥远。

答案 1 :(得分:2)

如果正确使用flex,可能是使用flex进行媒体查询可以帮助您。.我试图在jsfiddle上复制您的问题。

<div id="menu-container">
  <div class="menu"></div>
  <div class="menu"></div>
  <div class="menu">
      <div id="sub-menu-container">
          <div class="sub-menu" id="sub-menu1"></div>
          <div class="sub-menu" id="sub-menu2"></div>
          <div class="sub-menu" id="sub-menu3"></div>
          <div class="sub-menu" id="sub-menu4"></div>
      </div>
  </div>
  <div class="menu"></div>
</div>

CSS

.menu{
  border-radius:15px;
  background-color: #00ab9e;
  width:120px;
  height:50px;
  border: 1px solid #01eae9;
  display:inline-block;
  margin:5px;
  position:relative;
  vertical-align:top;
}
#sub-menu-container{
  margin-top:50px;
  display: flex;
  flex-flow: column wrap;
  align-items: flex-start;
}
.sub-menu{
  border-radius:15px;
  background-color: #ffb12a;
  width:120px;
  height:50px;
  border: 1px solid #01eae9;
  margin-top:5px;
}
#sub-menu2{
  width:150px;
}

#sub-menu3{
  width:200px;
}

@media only screen and (max-width: 495px) {
    #sub-menu-container {
      align-items: flex-end;
    }
}
@media only screen and (max-width: 420px) {
    #sub-menu-container {
      align-items: flex-start;
    }
}

https://jsfiddle.net/nimittshah/7bsf1r3v/

谢谢

答案 2 :(得分:0)

它看起来像是核心问题的答案:

是否有一种方法,仅通过CSS可以根据元素和其子元素的方向是更偏向屏幕的左侧还是右侧来更改其对正?

不是。

作为更详尽的后续回答,我想我要提到的是我不打算将原来的样式B下拉菜单固定在较小的屏幕尺寸上。我在问题中暗示了这一点,但越来越明显的是,我不能依靠屏幕大小来确定将来是否会截断下拉菜单。因此,鉴于现在已经排除了媒体查询,如果我想确保不为任何设备提供草率的解决方案,我需要另一种解决方案。

这让我留下了javascript。我试图避免这种情况,但是在现阶段,鉴于结果,我会很固执。

方法

万一它对其他人有用,我使用 jquery 为悬停在下拉菜单上提供了一个侦听器。逻辑是保证某个类的所有元素都具有一个下拉菜单,该菜单由另一个类的<ul>组成。这样我就可以轻松地将两者定位。

我可以检查下拉菜单是在屏幕的右侧还是左侧。这样会很好。挑剔的是,我宁愿菜单保持向左对齐,除非距屏幕右侧约200像素-这是我的动态内容的安全阈值。如果遇到问题,我可以去测量每个下拉宽度,并以此为阈值。

将所有这些放在一起。如果我将鼠标悬停在一个下拉菜单上,并且发现它距离屏幕右侧不到200像素,它将同时证明其菜单在右侧,并且将下拉菜单绝对定位在其父菜单标签的最右侧/ trigger(如我在原始插图中所示)。这样做的方式更灵活,更短,对于没有使用该库的任何人来说,没有 jquery 也不会有更多工作要做:

JS代码

$(nav).on('mouseover', '.dropdown', function() {

    var dropdownlist = $(this).children('ul');
    var screenWidth = $(window).width();
    var parentOffsetLeft = $(this).offset().left;
    var spaceRight = screenWidth - parentOffsetLeft;

    if (spaceRight < 200) {

        $(dropdownlist).css('text-align', 'right');
        $(dropdownlist).css('right', '0');
        $(dropdownlist).css('left', 'initial');

    } else {

        $(dropdownlist).css('text-align', 'left');
        $(dropdownlist).css('left', '0');
        $(dropdownlist).css('right', 'initial');

    }

});

使用此javascript,我可以重新创建问题中说明的解决方案。

答案 3 :(得分:0)

在您要调整文本对齐方式时,编写媒体查询以查询您的要求。您可以在media-query中更改测试的合理属性。根据您的要求使用不同的媒体查询来获得不同的显示尺寸,请参见示例

@media only screen and (max-width: 600px) {
selector {
    property : value;
}
}