Skip to content

min / max / step

minmaxstep 属性用于约束数值型、日期型和范围型输入控件的值。min 设置最小值,max 设置最大值,step 设置合法值的步进间隔。这三个属性协同工作,为数值和日期输入提供了精确的范围控制。

前置知识

阅读本节前,建议先了解:pattern 正则验证

基础概念

属性说明

属性说明适用类型
min允许的最小值number, range, date, time, datetime-local, month, week
max允许的最大值同上
step合法值的步进间隔同上

验证逻辑

当用户提交表单时,浏览器会检查:

  1. 值是否 >= min(如果设置了 min)
  2. 值是否 <= max(如果设置了 max)
  3. 值是否满足 step 的步进规则

语法

number 数值范围

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>min/max/step 数值</title>
</head>
<body>
    <h2>数量选择</h2>
    <form>
        <label for="quantity">数量:</label>
        <input
            type="number"
            id="quantity"
            name="quantity"
            min="1"
            max="99"
            step="1"
            value="1"
            required
        >
        <button type="submit">提交</button>
    </form>
</body>
</html>

date 日期范围

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>min/max 日期范围</title>
</head>
<body>
    <h2>预约日期</h2>
    <form>
        <label for="appointment-date">预约日期:</label>
        <input
            type="date"
            id="appointment-date"
            name="appointment_date"
            min="2025-07-15"
            max="2025-12-31"
            required
        >
        <button type="submit">提交</button>
    </form>
</body>
</html>

time 时间范围

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>min/max 时间范围</title>
</head>
<body>
    <h2>工作时间</h2>
    <form>
        <label for="work-time">选择时间:</label>
        <input
            type="time"
            id="work-time"
            name="work_time"
            min="09:00"
            max="18:00"
            step="1800"
            required
        >
        <button type="submit">提交</button>
    </form>
</body>
</html>

详细说明

step 步进规则

step 属性定义了合法值的间隔。浏览器验证 value 是否满足 (value - min) % step === 0(允许浮点误差)。

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>step 步进示例</title>
</head>
<body>
    <h2>step 步进控制</h2>
    <form>
        <div>
            <label for="int-step">整数步进(step=1):</label>
            <!-- 合法值:0, 1, 2, 3, 4, 5 -->
            <input type="number" id="int-step" min="0" max="5" step="1" value="0">
        </div>
        <div>
            <label for="float-step">小数步进(step=0.5):</label>
            <!-- 合法值:0, 0.5, 1, 1.5, 2, 2.5, 3 -->
            <input type="number" id="float-step" min="0" max="3" step="0.5" value="0">
        </div>
        <div>
            <label for="five-step">步进为5(step=5):</label>
            <!-- 合法值:0, 5, 10, 15, 20, 25, 30 -->
            <input type="number" id="five-step" min="0" max="30" step="5" value="0">
        </div>
        <div>
            <label for="any-step">任意值(step=any):</label>
            <!-- 任何值都合法 -->
            <input type="number" id="any-step" min="0" max="100" step="any">
        </div>
    </form>
</body>
</html>
step 值含义示例合法值(min=0, max=10)
1(默认)整数步进0, 1, 2, 3...
0.5半步进0, 0.5, 1, 1.5...
5每 5 个0, 5, 10
0.01精确到分0.00, 0.01, 0.02...
any不限制任意值

range 滑块的 min/max/step

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>range min/max/step</title>
    <style>
        body { font-family: sans-serif; max-width: 600px; margin: 40px auto; }
        .slider-group { margin-bottom: 16px; }
        label { display: block; margin-bottom: 4px; font-weight: 600; }
        input[type="range"] { width: 300px; }
    </style>
</head>
<body>
    <h2>滑块范围控制</h2>
    <form>
        <div class="slider-group">
            <label for="volume">音量(0-100,步进5):</label>
            <input type="range" id="volume" min="0" max="100" step="5" value="50">
            <output for="volume">50</output>
        </div>
        <div class="slider-group">
            <label for="temperature">温度(16-32,步进0.5):</label>
            <input type="range" id="temperature" min="16" max="32" step="0.5" value="24">
            <output for="temperature">24</output>
        </div>
        <div class="slider-group">
            <label for="zoom">缩放(1-10,步进0.1):</label>
            <input type="range" id="zoom" min="1" max="10" step="0.1" value="1">
            <output for="zoom">1</output>
        </div>
    </form>

    <script>
        document.querySelectorAll('form').forEach(form => {
            form.addEventListener('input', function () {
                this.querySelectorAll('input[type="range"]').forEach(range => {
                    range.nextElementSibling.value = range.value;
                });
            });
        });
    </script>
</body>
</html>

:out-of-range 和 :in-range 伪类

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>range 伪类</title>
    <style>
        body { font-family: sans-serif; max-width: 600px; margin: 40px auto; }
        input {
            padding: 8px 12px;
            border: 2px solid #ddd;
            border-radius: 6px;
            font-size: 16px;
        }
        /* 在范围内 */
        input:in-range {
            border-color: #27ae60;
        }
        /* 超出范围 */
        input:out-of-range {
            border-color: #e74c3c;
        }
    </style>
</head>
<body>
    <h2>范围伪类</h2>
    <form>
        <label for="age">年龄(18-65):</label>
        <input type="number" id="age" name="age" min="18" max="65" value="25">
        <p>输入超出 18-65 范围的值,边框会变红。</p>
    </form>
</body>
</html>

实战示例

商品数量选择器

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>商品数量</title>
    <style>
        body { font-family: sans-serif; max-width: 600px; margin: 40px auto; }
        .qty-control {
            display: flex;
            align-items: center;
            gap: 12px;
        }
        .qty-control button {
            width: 36px;
            height: 36px;
            border: 2px solid #ddd;
            border-radius: 6px;
            background: #fff;
            font-size: 18px;
            cursor: pointer;
        }
        .qty-control button:hover { background: #f0f0f0; }
        .qty-control input {
            width: 80px;
            text-align: center;
            font-size: 18px;
            padding: 6px;
            border: 2px solid #ddd;
            border-radius: 6px;
        }
        .price { font-size: 20px; color: #e74c3c; font-weight: bold; margin-top: 8px; }
    </style>
</head>
<body>
    <h2>商品数量</h2>
    <form>
        <div class="qty-control">
            <button type="button" onclick="adjustQty(-1)">-</button>
            <input type="number" id="qty" name="quantity" min="1" max="99" step="1" value="1"
                   oninput="updatePrice()">
            <button type="button" onclick="adjustQty(1)">+</button>
        </div>
        <p>单价:¥99.00</p>
        <p class="price">总价:<span id="total-price">¥99.00</span></p>
    </form>

    <script>
        const qtyInput = document.getElementById('qty');
        const price = 99;

        function adjustQty(delta) {
            let val = parseInt(qtyInput.value) || 1;
            val = Math.min(Math.max(val + delta, parseInt(qtyInput.min)), parseInt(qtyInput.max));
            qtyInput.value = val;
            updatePrice();
        }

        function updatePrice() {
            const qty = parseInt(qtyInput.value) || 1;
            document.getElementById('total-price').textContent = `¥${(qty * price).toFixed(2)}`;
        }
    </script>
</body>
</html>

注意事项

浮点数精度问题

step 为小数时可能出现浮点精度问题:

javascript
// 浏览器允许一定的浮点误差
// step=0.1, min=0, 输入 0.3 可能被认为是合法的

step=any 不限制步进

step="any" 表示不限制步进,但 minmax 的范围约束仍然有效。

range 控件永远在范围内

<input type="range"> 的值始终在 min/max 范围内(浏览器自动钳制),:out-of-range 对 range 控件无意义。

min > max 的情况

如果 min 大于 max,浏览器会忽略 min,使用 max 作为上界。

最佳实践

  1. 合理设置范围:min/max 应反映业务逻辑的实际约束
  2. 选择合适步进:步进值应根据业务精度需求设置
  3. 使用 number 输入步进器type="number" 提供上下箭头控制步进
  4. range 配合 output:滑块始终显示当前值
  5. 日期时间范围联动:起止日期/时间应联动更新 min/max
  6. 提供 :in-range/:out-of-range 样式:帮助用户感知范围约束

下一节

继续学习:minlength / maxlength

参考链接