是什么
calc() 是 CSS 原生支持的数学计算函数,全称是 “calculate”(计算)。
它允许你在 CSS 属性值中直接进行加减乘除运算,混合使用不同单位(如 %、px、rpx、em 等)。
calc()解决了什么问题?
场景:让一个固定宽度的元素水平居中
- 元素宽:
984rpx- 父容器宽:
100%- 想让它绝对定位居中
❌ 错误做法:
left: 50%; /* 元素左边缘在中心 */ /* 结果:元素整体偏右!因为 50% 是从左边开始算的 */✅正确思路:
把元素向左“拉回”自身宽度的一半
即:left = 50% - (width / 2)width: 984rpx; left: calc(50% - 492rpx); /* 984 / 2 = 492 */✅ 这样,元素的中心点就对齐了父容器的中心!
calc() 语法规则
property: calc(表达式);
| 运算符 | 说明 | 示例 |
|---|---|---|
+ |
加法 | calc(10px + 20px) |
- |
减法 | calc(100% - 20px) |
* |
乘法 | calc(2 * 50px) |
/ |
除法 | calc(100px / 2) |
- 运算符前后必须有空格
✅ 正确:calc(50% - 492rpx)
❌ 错误:calc(50%-492rpx)→ 浏览器会忽略整个规则! - 除法的右侧不能是 0,且必须是数值(不能是带单位的量)
✅ 正确:calc(100px / 2)
❌ 错误:calc(100px / 0)或calc(100px / 2px)
使用场景
固定边距的自适应宽度
需求:一个盒子,左右各留 40rpx 边距,中间自适应填满。
效果:无论屏幕多宽,盒子始终距离左右边缘 40rpx。
<template>
<view class="container">
<view class="box">自适应宽度</view>
</view>
</template>
<style scoped>
.container {
padding: 20rpx;
}
.box {
/* 宽度 = 100% - 左右边距(40rpx * 2) */
width: calc(100% - 80rpx);
height: 100rpx;
background-color: #4ecdc4;
border-radius: 16rpx;
}
</style>
绝对定位元素水平居中
需求:一个固定宽度的元素,在页面中水平居中(用 position: absolute)。
效果:红色盒子在灰色区域中水平居中。
<template>
<view class="page">
<view class="centered-box">我居中了</view>
</view>
</template>
<style scoped>
.page {
position: relative;
height: 300rpx;
background-color: #f0f0f0;
}
.centered-box {
position: absolute;
width: 200rpx;
height: 100rpx;
background-color: #ff6b6b;
border-radius: 16rpx;
/* 关键:left = 50% - 自身宽度一半 */
left: calc(50% - 100rpx); /* 200 / 2 = 100 */
top: 100rpx;
}
</style>
内容区高度 = 全屏 - 头部高度
需求:页面有固定高度的头部(120rpx),内容区占剩余高度。
效果:绿色内容区自动填满头部下方的所有空间。
<template>
<view class="page">
<view class="header">头部(120rpx)</view>
<view class="content">内容区(自动填满剩余高度)</view>
</view>
</template>
<style scoped>
.page {
height: 100vh; /* 全屏高度 */
display: flex;
flex-direction: column;
}
.header {
height: 120rpx;
background-color: #3498db;
color: white;
display: flex;
align-items: center;
justify-content: center;
}
.content {
/* 高度 = 全屏 - 头部高度 */
height: calc(100vh - 120rpx);
background-color: #2ecc71;
color: white;
display: flex;
align-items: center;
justify-content: center;
}
</style>
输入框左右有图标,中间自适应
需求:左侧图标(60rpx),右侧图标(60rpx),中间输入框填满。
效果:输入框自动适应中间剩余空间,图标固定宽度。
<template>
<view class="input-wrapper">
<text class="icon">🔍</text>
<input class="input" placeholder="请输入..." />
<text class="icon">✕</text>
</view>
</template>
<style scoped>
.input-wrapper {
display: flex;
align-items: center;
padding: 20rpx;
background-color: #fff;
border: 2rpx solid #ddd;
border-radius: 20rpx;
}
.icon {
width: 60rpx;
text-align: center;
font-size: 36rpx;
color: #888;
}
.input {
/* 宽度 = 100% - 左右图标宽度 */
width: calc(100% - 120rpx); /* 60 + 60 */
margin: 0 10rpx;
padding: 10rpx 0;
font-size: 28rpx;
}
</style>
两列布局,一列固定,一列自适应
需求:左侧头像(120rpx 宽),右侧信息自适应。
效果:右侧信息区自动填满头像右侧的剩余空间。
<template>
<view class="user-card">
<view class="avatar"></view>
<view class="info">
<view class="name">张三</view>
<view class="desc">前端工程师</view>
</view>
</view>
</template>
<style scoped>
.user-card {
display: flex;
padding: 20rpx;
background-color: #f8f9fa;
border-radius: 20rpx;
}
.avatar {
width: 120rpx;
height: 120rpx;
background-color: #ccc;
border-radius: 50%;
}
.info {
/* 宽度 = 100% - 头像宽度 - 间距 */
width: calc(100% - 120rpx - 20rpx);
margin-left: 20rpx;
}
.name {
font-size: 32rpx;
font-weight: bold;
}
.desc {
font-size: 28rpx;
color: #666;
margin-top: 10rpx;
}
</style>