CSS 具有颜色范围的条件格式
CSS Conditional Formatting with a colour range
我想使用 div 和 span 创建一个基本图表,并希望根据设置高度的值对图表中的每一列应用条件格式。我无法破解的技巧是我想让它的功能有点像此处示例中的 Excel 条件格式:
颜色在一个范围内(从浅到深)。
有没有简单的方法可以做到这一点?我可以看到如何将静态值应用于静态颜色,但希望我可以使用像这样的颜色范围来做一些事情 excel 示例。
因此,下面的屏幕截图显示了一个柱形图,其中每一列都有不同的橙色阴影,具体取决于列的值:
越接近25,颜色越深。同样,数值越小,橙色越浅。
我将提供两个选项,也许您可以根据您的需要提供更多详细信息。
第一个可能不是您想要的,因为它根据特定的高度设置了特定的渐变。只打算为此提供一个 Codepen。 https://codepen.io/jfirestorm44/pen/yLMNPPM?editors=1100
下一个更符合我的想法。如果您知道条形图的最大高度,您可以使用它来设置 linear-gradient
.
上的渐变中断
更新:
HTML
<div id="container">
<div id="first" class="bar"></div>
<div id="second" class="bar"></div>
<div id="third" class="bar"></div>
<div id="fourth" class="bar"></div>
<div id="fifth" class="bar"></div>
</div>
SCSS
.bar {
@for $i from 1 through 5 {
$height: 20px * $i;
$light: 75% + $i * -5;
&:nth-child(#{$i}) {
position: absolute;
bottom: 50%;
left: 20% + ($i * 10%);
width: 20px;
height: $height;
font-size: 25px;
transform: translate(-80%, 0);
background: hsl(35, 100%, $light);
}
}
}
更新的代码笔:https://codepen.io/jfirestorm44/pen/jOBPopj?editors=1100
添加 JS 选项:
let inputNum = document.getElementById("number");
let button1 = document.getElementById("button1");
let border = document.getElementById("border");
let dropDown = document.getElementById("cars");
function color() {
if (inputNum.value > 0) {
let bar = document.createElement("div");
bar.classList.add("bar");
border.appendChild(bar);
let bars = document.getElementsByClassName("bar");
let carName = document.createElement("p");
carName.classList.add("carType");
carName.textContent = cars.options[cars.selectedIndex].text;
border.appendChild(carName);
let names = document.getElementsByClassName("carType");
let height = inputNum.value * 26;
for (let i = 0; i < bars.length; i++) {
names[names.length - 1].style.top = "275px";
names[names.length - 1].style.left = -5 + i * 30 + "px";
bars[bars.length - 1].style.height = height + "px";
bars[bars.length - 1].style.backgroundColor =
"hsl(35, 100%," + (75 - height / 5.2) + "%)";
bars[bars.length - 1].style.left = 10 + i * 30 + "px";
}
}
}
#container {
position: absolute;
top: 40px;
left: 0;
width: 400px;
height: 300px;
}
#border {
position: relative;
left: 100%;
top: 0;
width: 90%;
height: 90%;
border-left: 2px solid grey;
border-bottom: 2px solid grey;
transform: translate(-100%, 0);
}
#numberContainer {
position: relative;
left: -5%;
}
.num {
line-height: 10px;
}
.num:before {
content: "";
position: absolute;
left: 18px;
width: 100%;
height: 10px;
border-bottom: 1px lightgrey solid;
}
.bar {
position: absolute;
bottom: 0;
width: 20px;
}
#button1 {
position: relative;
top: 0;
width: 60px;
height: 20px;
}
.car {
position: absolute;
top: 10px;
}
.carType {
position: absolute;
bottom: -85px;
writing-mode: vertical-rl;
text-orientation: upright;
}
<div id="container">
<div id="border">
<div id="numberContainer">
<p class="num">10</p>
<p class="num">9</p>
<p class="num">8</p>
<p class="num">7</p>
<p class="num">6</p>
<p class="num">5</p>
<p class="num">4</p>
<p class="num">3</p>
<p class="num">2</p>
<p class="num">1</p>
<p class="num">0</p>
</div>
</div>
</div>
<input type="number" min="0" max="10" value="0" id="number"/>
<label for="cars">Choose a car:</label>
<select name="cars" id="cars">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
<button type="button" onclick="color()" id="button1">Submit</button>
听起来您的目标是根据值在两种颜色之间的某处为条形着色。如果是这样,您可以使用 css 动画来模拟颜色渐变。
思路是这样的:
- 设置动画,将背景设置为两种颜色之一。这有效地计算了两种颜色之间的梯度。您可以使用
@keyframes
和 animation
.
- 暂停动画,因为我们不希望它实际播放。这是通过
animation-play-state
. 完成的
- Select 动画中的特定帧以获得正确的中间颜色。这可以用负
animation-delay
. 来完成
.bars {
display: flex;
justify-content: space-evenly;
}
.bar {
animation: color-gradient 25s linear 1;
animation-fill-mode: forwards;
animation-play-state: paused;
width: 3em;
}
@keyframes color-gradient {
from { background: red; }
to { background: blue; }
}
<div class="bars">
<div class="bar" style="height: 5em; animation-delay: -5s;"></div>
<div class="bar" style="height: 10em; animation-delay: -10s;"></div>
<div class="bar" style="height: 15em; animation-delay: -15s;"></div>
<div class="bar" style="height: 20em; animation-delay: -20s;"></div>
<div class="bar" style="height: 25em; animation-delay: -25s;"></div>
</div>
如果需要,可以通过使动画持续时间长于 25 秒来调整粒度。
[edit] 此答案仅从左到右为条形着色,左侧颜色最浅。
我会让容器有一个白色的背景和黑色的条,然后在所有东西上添加一个渐变,在伪元素的帮助下设置 mixed-blend-mode: lighten
只为黑色条着色.
作为奖励,我添加了另一个带有重复线性渐变的伪元素,该渐变由非常浅的灰色组成,以创建水平线。然后,我将 mixed-blend-mode: darken
添加到此元素,使它们出现在栏的“下方”。
我还通过为每个条随机化 CSS 属性 来随机化条的高度。
这个解决方案是可扩展的,所以不管你有多少个条形图,你仍然可以在所有条形图上得到一个渐变,而无需更改 CSS 代码。
let bars = document.querySelectorAll('.bar');
function randomize(max, min) {
min = min || 0;
return Math.floor(Math.random() * (max - min) + min);
}
for (const bar of bars) {
bar.style.setProperty('--bar-height', `${randomize(10, 2)}rem`);
}
.container {
position: relative;
display: inline-flex;
margin-left: 4.5rem;
align-items: flex-end;
background-color: #fff;
padding: 0px 1rem;
}
.container::before,
.container::after {
content: '';
position: absolute;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
}
.container::before {
background: linear-gradient(to right, #fbe5d6, #843c0c);
mix-blend-mode: lighten;
}
.container::after {
background: repeating-linear-gradient(to top, #f4f1f1, #f4f1f1 1px, transparent 1px, transparent 1rem);
z-index: 10;
mix-blend-mode: darken;
}
.bar {
width: 1.5rem;
height: var(--bar-height);
background-color: #000;
}
.bar + .bar {
margin-left: 3rem;
}
<div class="container">
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</div>
结合使用我和 Justin 的答案,但针对原版 CSS。
此答案使用 HSL 和 CSS 变量来设置颜色和高度。
随机值
let bars = document.querySelectorAll('.bar');
function randomize(max, min) {
min = min || 0;
return Math.floor(Math.random() * (max - min) + min);
}
for (const bar of bars) {
let maxValue = 25;
let randomValue = randomize(maxValue, 2);
let height = randomValue/2;
let hue = '24deg';
let saturation = '82%';
let maxHue = 90;
let minHue = 30;
let hueRange = maxHue - minHue;
let lightness = `${maxHue - hueRange * (randomValue/maxValue)}%`;
bar.style.setProperty('--bar-height', `${height}rem`);
bar.style.setProperty('--color-background-bar', `hsl(${hue}, ${saturation}, ${lightness})`);
}
.container {
display: inline-flex;
margin-left: 4.5rem;
align-items: flex-end;
padding: 0px 1rem;
background: repeating-linear-gradient(to top, #eee, #eee 1px, transparent 1px, transparent 1rem);
}
.bar {
width: 1.5rem;
height: var(--bar-height);
background-color: var(--color-background-bar);
}
.bar + .bar {
margin-left: 3rem;
}
<div class="container">
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</div>
增加价值
从 5 到 25 的静态值,如 OP 的图片所示。
let bars = document.querySelectorAll('.bar');
bars.forEach((bar, index) => {
let maxValue = 25;
let customValue = 5 + index * 5;
let height = customValue/2;
let hue = '24deg';
let saturation = '82%';
let maxHue = 90;
let minHue = 30;
let hueRange = maxHue - minHue;
let lightness = `${maxHue - hueRange * (customValue/maxValue)}%`;
bar.style.setProperty('--bar-height', `${height}rem`);
bar.style.setProperty('--color-background-bar', `hsl(${hue}, ${saturation}, ${lightness})`);
});
.container {
display: inline-flex;
margin-left: 4.5rem;
align-items: flex-end;
padding: 0px 1rem;
background: repeating-linear-gradient(to top, #eee, #eee 1px, transparent 1px, transparent 1rem);
}
.bar {
width: 1.5rem;
height: var(--bar-height);
background-color: var(--color-background-bar);
}
.bar + .bar {
margin-left: 3rem;
}
<div class="container">
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</div>
我想使用 div 和 span 创建一个基本图表,并希望根据设置高度的值对图表中的每一列应用条件格式。我无法破解的技巧是我想让它的功能有点像此处示例中的 Excel 条件格式:
颜色在一个范围内(从浅到深)。 有没有简单的方法可以做到这一点?我可以看到如何将静态值应用于静态颜色,但希望我可以使用像这样的颜色范围来做一些事情 excel 示例。
因此,下面的屏幕截图显示了一个柱形图,其中每一列都有不同的橙色阴影,具体取决于列的值:
越接近25,颜色越深。同样,数值越小,橙色越浅。
我将提供两个选项,也许您可以根据您的需要提供更多详细信息。
第一个可能不是您想要的,因为它根据特定的高度设置了特定的渐变。只打算为此提供一个 Codepen。 https://codepen.io/jfirestorm44/pen/yLMNPPM?editors=1100
下一个更符合我的想法。如果您知道条形图的最大高度,您可以使用它来设置 linear-gradient
.
更新: HTML
<div id="container">
<div id="first" class="bar"></div>
<div id="second" class="bar"></div>
<div id="third" class="bar"></div>
<div id="fourth" class="bar"></div>
<div id="fifth" class="bar"></div>
</div>
SCSS
.bar {
@for $i from 1 through 5 {
$height: 20px * $i;
$light: 75% + $i * -5;
&:nth-child(#{$i}) {
position: absolute;
bottom: 50%;
left: 20% + ($i * 10%);
width: 20px;
height: $height;
font-size: 25px;
transform: translate(-80%, 0);
background: hsl(35, 100%, $light);
}
}
}
更新的代码笔:https://codepen.io/jfirestorm44/pen/jOBPopj?editors=1100
添加 JS 选项:
let inputNum = document.getElementById("number");
let button1 = document.getElementById("button1");
let border = document.getElementById("border");
let dropDown = document.getElementById("cars");
function color() {
if (inputNum.value > 0) {
let bar = document.createElement("div");
bar.classList.add("bar");
border.appendChild(bar);
let bars = document.getElementsByClassName("bar");
let carName = document.createElement("p");
carName.classList.add("carType");
carName.textContent = cars.options[cars.selectedIndex].text;
border.appendChild(carName);
let names = document.getElementsByClassName("carType");
let height = inputNum.value * 26;
for (let i = 0; i < bars.length; i++) {
names[names.length - 1].style.top = "275px";
names[names.length - 1].style.left = -5 + i * 30 + "px";
bars[bars.length - 1].style.height = height + "px";
bars[bars.length - 1].style.backgroundColor =
"hsl(35, 100%," + (75 - height / 5.2) + "%)";
bars[bars.length - 1].style.left = 10 + i * 30 + "px";
}
}
}
#container {
position: absolute;
top: 40px;
left: 0;
width: 400px;
height: 300px;
}
#border {
position: relative;
left: 100%;
top: 0;
width: 90%;
height: 90%;
border-left: 2px solid grey;
border-bottom: 2px solid grey;
transform: translate(-100%, 0);
}
#numberContainer {
position: relative;
left: -5%;
}
.num {
line-height: 10px;
}
.num:before {
content: "";
position: absolute;
left: 18px;
width: 100%;
height: 10px;
border-bottom: 1px lightgrey solid;
}
.bar {
position: absolute;
bottom: 0;
width: 20px;
}
#button1 {
position: relative;
top: 0;
width: 60px;
height: 20px;
}
.car {
position: absolute;
top: 10px;
}
.carType {
position: absolute;
bottom: -85px;
writing-mode: vertical-rl;
text-orientation: upright;
}
<div id="container">
<div id="border">
<div id="numberContainer">
<p class="num">10</p>
<p class="num">9</p>
<p class="num">8</p>
<p class="num">7</p>
<p class="num">6</p>
<p class="num">5</p>
<p class="num">4</p>
<p class="num">3</p>
<p class="num">2</p>
<p class="num">1</p>
<p class="num">0</p>
</div>
</div>
</div>
<input type="number" min="0" max="10" value="0" id="number"/>
<label for="cars">Choose a car:</label>
<select name="cars" id="cars">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
<button type="button" onclick="color()" id="button1">Submit</button>
听起来您的目标是根据值在两种颜色之间的某处为条形着色。如果是这样,您可以使用 css 动画来模拟颜色渐变。
思路是这样的:
- 设置动画,将背景设置为两种颜色之一。这有效地计算了两种颜色之间的梯度。您可以使用
@keyframes
和animation
. - 暂停动画,因为我们不希望它实际播放。这是通过
animation-play-state
. 完成的
- Select 动画中的特定帧以获得正确的中间颜色。这可以用负
animation-delay
. 来完成
.bars {
display: flex;
justify-content: space-evenly;
}
.bar {
animation: color-gradient 25s linear 1;
animation-fill-mode: forwards;
animation-play-state: paused;
width: 3em;
}
@keyframes color-gradient {
from { background: red; }
to { background: blue; }
}
<div class="bars">
<div class="bar" style="height: 5em; animation-delay: -5s;"></div>
<div class="bar" style="height: 10em; animation-delay: -10s;"></div>
<div class="bar" style="height: 15em; animation-delay: -15s;"></div>
<div class="bar" style="height: 20em; animation-delay: -20s;"></div>
<div class="bar" style="height: 25em; animation-delay: -25s;"></div>
</div>
如果需要,可以通过使动画持续时间长于 25 秒来调整粒度。
[edit] 此答案仅从左到右为条形着色,左侧颜色最浅。
我会让容器有一个白色的背景和黑色的条,然后在所有东西上添加一个渐变,在伪元素的帮助下设置 mixed-blend-mode: lighten
只为黑色条着色.
作为奖励,我添加了另一个带有重复线性渐变的伪元素,该渐变由非常浅的灰色组成,以创建水平线。然后,我将 mixed-blend-mode: darken
添加到此元素,使它们出现在栏的“下方”。
我还通过为每个条随机化 CSS 属性 来随机化条的高度。
这个解决方案是可扩展的,所以不管你有多少个条形图,你仍然可以在所有条形图上得到一个渐变,而无需更改 CSS 代码。
let bars = document.querySelectorAll('.bar');
function randomize(max, min) {
min = min || 0;
return Math.floor(Math.random() * (max - min) + min);
}
for (const bar of bars) {
bar.style.setProperty('--bar-height', `${randomize(10, 2)}rem`);
}
.container {
position: relative;
display: inline-flex;
margin-left: 4.5rem;
align-items: flex-end;
background-color: #fff;
padding: 0px 1rem;
}
.container::before,
.container::after {
content: '';
position: absolute;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
}
.container::before {
background: linear-gradient(to right, #fbe5d6, #843c0c);
mix-blend-mode: lighten;
}
.container::after {
background: repeating-linear-gradient(to top, #f4f1f1, #f4f1f1 1px, transparent 1px, transparent 1rem);
z-index: 10;
mix-blend-mode: darken;
}
.bar {
width: 1.5rem;
height: var(--bar-height);
background-color: #000;
}
.bar + .bar {
margin-left: 3rem;
}
<div class="container">
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</div>
结合使用我和 Justin 的答案,但针对原版 CSS。
此答案使用 HSL 和 CSS 变量来设置颜色和高度。
随机值
let bars = document.querySelectorAll('.bar');
function randomize(max, min) {
min = min || 0;
return Math.floor(Math.random() * (max - min) + min);
}
for (const bar of bars) {
let maxValue = 25;
let randomValue = randomize(maxValue, 2);
let height = randomValue/2;
let hue = '24deg';
let saturation = '82%';
let maxHue = 90;
let minHue = 30;
let hueRange = maxHue - minHue;
let lightness = `${maxHue - hueRange * (randomValue/maxValue)}%`;
bar.style.setProperty('--bar-height', `${height}rem`);
bar.style.setProperty('--color-background-bar', `hsl(${hue}, ${saturation}, ${lightness})`);
}
.container {
display: inline-flex;
margin-left: 4.5rem;
align-items: flex-end;
padding: 0px 1rem;
background: repeating-linear-gradient(to top, #eee, #eee 1px, transparent 1px, transparent 1rem);
}
.bar {
width: 1.5rem;
height: var(--bar-height);
background-color: var(--color-background-bar);
}
.bar + .bar {
margin-left: 3rem;
}
<div class="container">
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</div>
增加价值
从 5 到 25 的静态值,如 OP 的图片所示。
let bars = document.querySelectorAll('.bar');
bars.forEach((bar, index) => {
let maxValue = 25;
let customValue = 5 + index * 5;
let height = customValue/2;
let hue = '24deg';
let saturation = '82%';
let maxHue = 90;
let minHue = 30;
let hueRange = maxHue - minHue;
let lightness = `${maxHue - hueRange * (customValue/maxValue)}%`;
bar.style.setProperty('--bar-height', `${height}rem`);
bar.style.setProperty('--color-background-bar', `hsl(${hue}, ${saturation}, ${lightness})`);
});
.container {
display: inline-flex;
margin-left: 4.5rem;
align-items: flex-end;
padding: 0px 1rem;
background: repeating-linear-gradient(to top, #eee, #eee 1px, transparent 1px, transparent 1rem);
}
.bar {
width: 1.5rem;
height: var(--bar-height);
background-color: var(--color-background-bar);
}
.bar + .bar {
margin-left: 3rem;
}
<div class="container">
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</div>