如何使用CSS calc()函数来计算元素的高度

67

我在研究如何仅使用CSS制作正六边形,并找到了一种以宽度为基础给出规则正六边形的方法:

.hexagon {
  height: 100%;
  width: calc(100% * 0.57735);
  display: inline-block;
}

然而,此代码是基于父元素的宽度生成新矩形。我正在寻找一种方法,通过父元素的高度来计算宽度。

是否有一种方法可以使用元素的高度属性而不是宽度属性来进行calc()计算?(我不考虑使用vh,因为最近的父级不总是视口)。我在谷歌上搜索了一下,但没有找到答案。


Note to translator: Please translate the content in between the

tags and keep the HTML tags.


1
@RafaRomero 我想知道是否有一种简单的方法可以不使用SASS或LESS,但请回答你的答案,可能会很有帮助。 - Luciano
3
calc()函数不使用任何东西的宽度,它仅仅在左右两侧通过运算符进行简单的操作。因此,在相对值(如此处的100%)的情况下,它首先将该值转换为绝对值。注意,你不能传递另一个元素的相对值或其他属性。 - Kaiido
@dakab 我问这个问题是因为首先我想知道他/她是否想使用其他技术。 - Rafa Romero
@Luciano 没有错,100vw 是一个相对长度(相对于视口而不是任何元素)。例如,这不一定与 documentElement 的宽度相同 http://jsfiddle.net/2bxbd3w5/ - Kaiido
这段代码甚至不需要“calc”,因为它和“57.735%”是一样的。 - Mr Lister
显示剩余5条评论
5个回答

91

我认为你正在尝试在css语法中运行脚本,这是不可能的

calc()可以使用绝对值进行基本数学运算,但它无法找到一个元素的高度然后对其进行数学运算。


8
这该怎么做的替代方案是什么? - Halo
1
另一种选择是JavaScript。或者在React中,使用useEffect来查找元素的高度,并基于此进行计算。创建一个函数来执行此操作,以便您也可以将其用于window.resize事件。 - Aamir Afridi
许多涉及计算的问题可以使用Flexbox或GridLayout解决。 - danilo

31

您可以通过使用中间代理来解决问题:CSS变量,这是花括号之外唯一的数据。

如果父元素的宽度也是动态或依赖于其他值,请使用另一个 var。这只是一个示例,以便您可以看到语法,它可能像这样:

:root {
  --hex-parent-height: 10px;
}

.hexagon.parent {
  /* ... */
  width: var(--hex-parent-height);
}

.hexagon {
  height: 100%;
  width: calc(100% * var(--hex-parent-height));
  display: inline-block;
}

CSS变量有两种作用域:全局和局部。局部变量只在同一选择器内逻辑上起作用,但全局变量在整个CSS中都是相同的。通过根块声明一个或多个全局变量,如代码示例所示。

如您所见,检索变量值就像使用var() CSS函数一样容易,该函数具有非常好的回退功能。

例如,如果您需要动态设置--hex-parent-height,并且出现了错误并且未设置变量,则可以插入默认值来减少损失,如下所示:var(--hex-parent-height, 10px)


7
是的,但这些仍然取决于在:root中设置的固定值。不幸的是,无法使用动态值,因此我已经放弃了......也许有一天我们会有它! - Luciano
1
除非您可以从JS更新CSS变量https://css-tricks.com/updating-a-css-variable-with-javascript/ - Ivan Carmenates García
1
我最初不喜欢这个答案(如果我们使用JS,为什么不完全使用JS?),但是我改变了主意 - 使用JS设置CSS变量允许我们在CSS中执行所有“其他”计算,从而简化了其余的布局/动画。 - rinogo

6

正如@YAMAN所说,这是不可能的,但我有一个诀窍与你分享,以防它起作用并帮助你。

top: calc(50% - 0.59em);

为了测试它,给定一个具有大小和文本内容的div,您可以增加字体大小,手动获取高度并将其除以2,用该值替换0.59em,您可能会看到它们保持在同一px中。
请注意,我已经知道这不是100%准确的,但对于少数情况而言它相当有效,请自行检查,可能适合您的情况,也可能不适合。

do not use any margins - Alejandro Lora

2

正如许多人多次指出的那样,使用纯CSS无法基于100%高度设置宽度。

如果您知道或可以计算出宽高比,那么您就可以从技术上知道宽度,并且可以相对容易地计算出它。

.wrapper {
    position: relative;
    width: 100%;
    padding-top: 56.25%; /* 16:9 or widescreen aspect ratio */
}
.hexagon {
    top: 0;
    position: absolute;
    width: calc(100% * 9 / 16); /* or simply 56.25%; */
}

如果宽高比未知,则使用CSS的唯一可行解决方案是使用pxem值设置父元素的高度(或最小高度)。这些也可以使用CSS变量设置,尽管某些旧版浏览器不完全支持CSS变量。

.wrapper {
    min-height: 400px;
}
.hexagon {
    width: calc(400px * 0.57735);
}

最后,如果高度完全是动态的,例如它基于文本行数变化而变化,那么宽度将需要使用JavaScript来计算。

// Example using jQuery, but the principles should be the same.
jQuery(function($){
    var hexagon = $('.hexagon');
    // Resizing the document may change the height of the parent element.
    $(window).on('resize', function() {
        hexagon.each(function(){
            // We'll remove the existing width before calling parent.height()
            $(this).css({width:''}).css({width:$(this).parent().height()});
        });
    }).trigger('resize');
});

请注意,如果父元素的大小在子元素更改时发生变化,JavaScript解决方案可能无法提供您正在寻找的精确结果。这也是使用CSS的高度值时面临的挑战的一部分,几乎所有内容都基于宽度而不是高度。

2

我建议定义一个基于CSS变量(如Carles Alcolea所提出的)的CSS规则,并实现一个JavaScript代码来更新CSS变量的值。

  1. 定义使用var()的CSS。
.hexagon.parent {
  /* ... */
  width: var(--hex-parent-height);
}

在HTML中创建一个占位符来保存变量定义。
<style id="my-dyn-css">
/* dynamically define css vars here */
</style>
  1. 定义一个函数来设置和更新变量的值(例如在窗口调整大小时)
function updateDynCss() {
  var parentHeight = computeHeight();
  var style = ":root{--hex-parent-height:" + parentHeight + "px;}";
  $("#my-dyn-css").empty().html(style);
}

1
为什么要这么复杂呢?不如直接用JS更新样式。 - Luciano
你是对的,Luciano,这并不是绝对必要的。但它有助于代码的可读性和可重用性(您可以在其他CSS声明中重复使用变量)。例如,我使用这种方法来定义保存主色调变化的变量。 - Antonio Capani

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接