From 5519f6cdb9446cdd70cd7c45baee3560a263c2b8 Mon Sep 17 00:00:00 2001 From: Patrick Kettner Date: Wed, 15 Jul 2026 05:17:29 -0400 Subject: [PATCH] Box-model rule now honors box-sizing on the universal selector. Fixes #243 --- src/rules/box-model.js | 42 ++++++++++++++++++++++++++++++++++++---- tests/rules/box-model.js | 36 ++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/src/rules/box-model.js b/src/rules/box-model.js index 09e02197..3d9315f0 100644 --- a/src/rules/box-model.js +++ b/src/rules/box-model.js @@ -31,11 +31,31 @@ CSSLint.addRule({ "padding-top": 1 }, properties, - boxSizing = false; + boxSizing = false, + selectors, + universalBoxSizing = false, + warnings = []; + + // the universal selector (*) applies to all elements, + // so a box-sizing declared there makes the warnings unnecessary + function hasUniversalSelector() { + var i, part; + + for (i = 0; i < selectors.length; i++) { + if (selectors[i].parts.length === 1) { + part = selectors[i].parts[0]; + if (part.elementName === "*" && part.modifiers.length === 0) { + return true; + } + } + } + return false; + } - function startRule() { + function startRule(event) { properties = {}; boxSizing = false; + selectors = event.selectors; } function endRule() { @@ -48,7 +68,7 @@ CSSLint.addRule({ value = properties[prop].value; // special case for padding if (!(prop === "padding" && value.parts.length === 2 && value.parts[0].value === 0)) { - reporter.report("Using height with " + prop + " can sometimes make elements larger than you expect.", properties[prop].line, properties[prop].col, rule); + warnings.push({ message: "Using height with " + prop + " can sometimes make elements larger than you expect.", line: properties[prop].line, col: properties[prop].col }); } } } @@ -60,7 +80,7 @@ CSSLint.addRule({ value = properties[prop].value; if (!(prop === "padding" && value.parts.length === 2 && value.parts[1].value === 0)) { - reporter.report("Using width with " + prop + " can sometimes make elements larger than you expect.", properties[prop].line, properties[prop].col, rule); + warnings.push({ message: "Using width with " + prop + " can sometimes make elements larger than you expect.", line: properties[prop].line, col: properties[prop].col }); } } } @@ -91,6 +111,9 @@ CSSLint.addRule({ properties[name] = 1; } else if (name === "box-sizing") { boxSizing = true; + if (selectors && hasUniversalSelector()) { + universalBoxSizing = true; + } } } @@ -102,6 +125,17 @@ CSSLint.addRule({ parser.addListener("endpagemargin", endRule); parser.addListener("endkeyframerule", endRule); parser.addListener("endviewport", endRule); + + parser.addListener("endstylesheet", function() { + var i; + + if (universalBoxSizing) { + return; + } + for (i = 0; i < warnings.length; i++) { + reporter.report(warnings[i].message, warnings[i].line, warnings[i].col, rule); + } + }); } }); diff --git a/tests/rules/box-model.js b/tests/rules/box-model.js index 209c1f10..fc149755 100644 --- a/tests/rules/box-model.js +++ b/tests/rules/box-model.js @@ -13,6 +13,42 @@ Assert.areEqual("Using width with padding can sometimes make elements larger than you expect.", result.messages[0].message); }, + "Using width and padding when the universal selector declares box-sizing should not result in a warning": function() { + var result = CSSLint.verify("* { box-sizing: border-box; } .foo { width: 100px; padding: 10px; }", { "box-model": 1 }); + Assert.areEqual(0, result.messages.length); + }, + + "Using width and padding when a universal selector group declares box-sizing should not result in a warning": function() { + var result = CSSLint.verify("*, *:before, *:after { box-sizing: border-box; } .foo { width: 100px; padding: 10px; }", { "box-model": 1 }); + Assert.areEqual(0, result.messages.length); + }, + + "Using width and padding before the universal selector declares box-sizing should not result in a warning": function() { + var result = CSSLint.verify(".foo { width: 100px; padding: 10px; } * { box-sizing: border-box; }", { "box-model": 1 }); + Assert.areEqual(0, result.messages.length); + }, + + "Using width and padding when another selector declares box-sizing should result in a warning": function() { + var result = CSSLint.verify(".bar { box-sizing: border-box; } .foo { width: 100px; padding: 10px; }", { "box-model": 1 }); + Assert.areEqual(1, result.messages.length); + Assert.areEqual("warning", result.messages[0].type); + Assert.areEqual("Using width with padding can sometimes make elements larger than you expect.", result.messages[0].message); + }, + + "Using width and padding when a qualified universal selector declares box-sizing should result in a warning": function() { + var result = CSSLint.verify("*.bar { box-sizing: border-box; } .foo { width: 100px; padding: 10px; }", { "box-model": 1 }); + Assert.areEqual(1, result.messages.length); + Assert.areEqual("warning", result.messages[0].type); + Assert.areEqual("Using width with padding can sometimes make elements larger than you expect.", result.messages[0].message); + }, + + "Using width and padding when a descendant universal selector declares box-sizing should result in a warning": function() { + var result = CSSLint.verify("div * { box-sizing: border-box; } .foo { width: 100px; padding: 10px; }", { "box-model": 1 }); + Assert.areEqual(1, result.messages.length); + Assert.areEqual("warning", result.messages[0].type); + Assert.areEqual("Using width with padding can sometimes make elements larger than you expect.", result.messages[0].message); + }, + "Using width when padding is zero should not result in a warning": function() { var result = CSSLint.verify(".foo { width: 100px; padding: 0; }", { "box-model": 1 }); Assert.areEqual(0, result.messages.length);