Hi I am trying to create a highlight on a CSS shape as shown below.
There will also be content inside of the hexagon including image and text,
The highlight I am referring to is the part in the top left.
the code I currently have for creating the hexagon is:
HTML
<div class="hexagon-big"></div>
CSS
.hexagon-big {
position: relative;
width: 200px;
height: 115.47px;
background-color: #343434;
}
.hexagon-big:before,
.hexagon-big:after {
content: "";
position: absolute;
width: 0;
border-left: 100px solid transparent;
border-right: 100px solid transparent;
}
.hexagon-big:before {
bottom: 100%;
border-bottom: 57.74px solid #343434;
}
.hexagon-big:after {
top: 100%;
width: 0;
border-top: 57.74px solid #343434;
}
There is other code for the content but i left it out because I don't think it is necessary
Do the hexagon shape differently and you can rely on gradient to create that highlight effect:
.hex {
width: 200px;
display: inline-flex;
margin:0 5px;
background:
conic-gradient(at top,#000 230deg, #0000 0),
linear-gradient(to bottom left,#fff , #000 60%);
clip-path: polygon(0% 25%,0% 75%,50% 100%,100% 75%,100% 25%,50% 0%);
}
.hex::before {
content: "";
padding-top: 115%; /* 100%/cos(30) */
}
<div class="hex"></div>
The solution in this answer is heavily based on the previous answer. To use clip-path and stacked gradients is by far the smartest thing to do here, but I still wanted to post this in order to show, how this solution could be improved and adjusted for your use case (text box, coloring, variables for maintenance, etc.).
.hexagon-big {
/* define box and text space */
width: 200px;
height: 230px;
padding: 10.8% 5px; /* adjust text box padding here; mind that top/bottom tip are part of the box */
box-sizing: border-box; /* width/height should include padding */
/* text formatting (optional) */
color: white;
text-align: center;
/* hex shape */
--hex-col: hsl(0deg 0% 20%); /* just your #343434 as a HSL color */
--hex-shadow: hsl(0deg 0% 50%); /* increased lightness by 15% to define highlight root color; 100% would be fully white */
background:
conic-gradient(at top, var(--hex-col) 232deg, transparent 0), /* change the angle of the shadow at "232deg": increase → narrower, decrease → wider */
linear-gradient(to bottom left, var(--hex-shadow), var(--hex-col) 55%);
clip-path: polygon(0% 25%,0% 75%,50% 100%,100% 75%,100% 25%,50% 0%);
}
<div class="hexagon-big">
Lorem ipsum dolor sit amet...
</div>
It should also be mentioned that your current way of using border is well better supported by older browsers than clip-path and conic-gradient (same with var()).
If this should be a problem, you might have to add another HTML tag and work out a way with transform: matrix(...) and box-shadow: inset ... (for example).
The following is a minimal (ish) example in which a chequered gradient fill pattern is glitchy in Firefox (version 74) i.e. it is not pixel perfect. There are line artefacts. Why is this? Is that normal? Is there a fix, other than using an image for the background?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width" />
<style>
.r{width:20px;height:20px;background:white;float:left;}
.w{overflow:hidden;}
#p75{
width:80px;
height:20px;
background-position:0px 0px,10px 10px;
background-size:20px 20px;
background-image:linear-gradient(45deg,#ccc 25%,transparent 25%,transparent 75%,#ccc 75%,#ccc 100%),
linear-gradient(45deg,#ccc 25%,white 25%,white 75%,#ccc 75%,#ccc 100%);
float:left;
}
</style>
</head>
<body>
<div class="w">
<div class="r">0</div>
<div id="p75"></div>
</div>
</body>
Rotating gradients have always had that problem for more on that check this question
One way to fix the issue is to not use angles at all, and make use of repeating gradients.
html {
height: 100%;
background:
repeating-linear-gradient(90deg, #fff 0px 10px, transparent 10px 20px),
repeating-linear-gradient(0deg, #000 0px 10px, #fff 10px 20px);
background-blend-mode: difference;
}
Edit: thanks to #Temani Afif without repeating gradient.
html {
height: 100%;
background:
linear-gradient(90deg, #fff 50%, transparent 0) 0 0/20px 100%,
linear-gradient(0deg, #000 50%, #fff 0) 0 0/100% 20px;
background-blend-mode: difference;
}
you can overlap them a tiny bit , here i added 0.1% to the color start/stop setup , chrome use to be the one.
.r {
width: 20px;
height: 20px;
background: white;
float: left;
}
.w {
overflow: hidden;
}
#p75,
.p75 {
width: 80px;
height: 20px;
background-position: 0px 0px, 10px 10px;
background-size: 20px 20px;
background-image: linear-gradient(45deg, #ccc 25%, transparent 25.1%, transparent 75%, #ccc 75.1%, #ccc 100%), linear-gradient(45deg, #ccc 25%, white 25.1%, white 75%, #ccc 75.1%, #ccc 100%);
float: left;
}
.p75 {
margin:0 1em 1em;
height: 200px;
width:100%;
background-size: 19px 19px;
<div class="w">
<div class="r">0</div>
<div id="p75"></div>
</div>
<p>or decrease background-size of 1px</p>
<div class="p75"></div>
Another solution is to set the whole pattern from triangles and pretune values via css custom properties :
div {
--bgsize: 40;
--sq1: 0 0;
--sq2: calc(var(--bgsize) / 2 * 1px) calc(var(--bgsize) / 2 * 1px);
--sq3: var(--sq2);
--sq4: calc(var(--bgsize) * 1px ) 0px;
}
#a20:checked ~ div { --bgsize: 20; }
#a50:checked ~ div { --bgsize: 50; }
#a150:checked~ div { --bgsize: 150;}
#a100:checked~ div { --bgsize: 100;}
div {
height:200px;
background:
linear-gradient(45deg, gray 25% , transparent 26%),
linear-gradient(225deg, gray 25% , transparent 26%),
linear-gradient(45deg, gray 25% , transparent 26%),
linear-gradient(225deg, gray 25% , transparent 26%)
;
background-position:
var(--sq1) ,
var(--sq2) ,
var(--sq3) ,
var(--sq4);
background-size: calc(var(--bgsize) * 1px) calc(var(--bgsize) * 1px );
}
reset bg-size:<br>
<label for=a20>20px</label><input type=radio name=test id=a20>
<label for=a100>100px</label><input type=radio name=test id=a100>
<label for=a150>150px</label><input type=radio name=test id=a150>
<div></div>
demo with option to reset --bgsize and color
https://codepen.io/gc-nomade/pen/GRJGXwv
For background-image you can add as many radial-gradient and/or linear-gradient you want. But for border-image it seems like you can only add one. If find it quite strange, because the principle of how to display gradients should be the same for border and background, right?
Is there a way to add more than one gradient in border-image? I'm only interested in a pure CSS solution.
This doesn't work, because it contains more than 1 gradient:
div {
height: 30px;
width: 40px;
border: 50px solid black;
border-image:
radial-gradient(circle at 20px 30px, green 20px, rgba(0,0,255, .5) 20px),
radial-gradient(30deg, blue 22px, red 22px);
}
https://jsfiddle.net/thadeuszlay/p6r2p78g/
This works, but contains only one gradient:
div {
height: 30px;
width: 40px;
border: 50px solid black;
border-image: radial-gradient(circle at 20px 30px, green 20px, rgba(0, 0, 255, .5) 20px);
}
https://jsfiddle.net/thadeuszlay/p6r2p78g/1/
No, you can't set more than one image to the border-image shorthand or the border-image-source longhand property.
As per spec for border-image-source, we can see that only one image layer is specified as value.
Name: border-image-source
Value: none | <image>
whereas for background-image, we can see that multiple layers are specified.
Name: background-image
Value: <bg-image> [ , <bg-image> ]*
Below is an extract from the spec which introduces layering of background images: (emphasis mine)
The background of a box can have multiple layers in CSS3. The number of layers is determined by the number of comma-separated values in the ‘background-image’ property.
Just stubled upon this question when I was looking for the same thing.
But for other people, trying this:
You could just add a pseudo-element, and give that one a border too.
Guessing you would use transparent, because otherwise multiple gradients wouldn't be visible at all.
I've got the following:
h1{
--border-width: 5px;
border-width: var(--border-width);
border-style: solid;
border-image: linear-gradient(135deg, #ff0000, transparent 20%);
border-image-slice: 1;
font-size: 5rem;
position: relative;
}
h1::after{
position: absolute;
inset: calc(var(--border-width) * -1);
content: '';
background: transparent;
border-width: var(--border-width);
border-style: solid;
border-image: linear-gradient(135deg, transparent 80%, #ff0000 100%);
border-image-slice: 1;
}
I set the inset of the pseudo element to negative the border-width to make sure it aligns with the parents border.
I am wondering how I could style the new <meter> tag.
<meter value=80 min=0 max=100>
80/100
</meter>
I just want to change the background color and the value color, but I can't find the right CSS properties.
For webkit-based browsers I've found these:
meter::-webkit-meter-horizontal-bar {
-webkit-appearance: meter;
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#DDD), color-stop(0.2, #EEE), color-stop(0.45, #CCC), color-stop(0.55, #CCC), to(#DDD));
}
Pseudo element
meter::-webkit-meter-horizontal-optimum-value {
-webkit-appearance: meter;
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#AD7), color-stop(0.2, #CEA), color-stop(0.45, #7A3), color-stop(0.55, #7A3), to(#AD7));
}
Pseudo element
meter::-webkit-meter-horizontal-suboptimal-value {
-webkit-appearance: meter;
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#FE7), to(#FE7), color-stop(0.2, #FFC), color-stop(0.45, #DB3), color-stop(0.55, #DB3));
}
Pseudo element
meter::-webkit-meter-horizontal-even-less-good-value {
-webkit-appearance: meter;
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#F77), to(#F77), color-stop(0.2, #FCC), color-stop(0.45, #D44), color-stop(0.55, #D44));
}
Pseudo element
meter::-webkit-meter-vertical-bar {
-webkit-appearance: meter;
background: -webkit-gradient(linear, 0% 0%, 100% 0%, from(#DDD), to(#DDD), color-stop(0.2, #EEE), color-stop(0.45, #CCC), color-stop(0.55, #CCC));
}
Pseudo element
meter::-webkit-meter-vertical-optimum-value {
-webkit-appearance: meter;
background: -webkit-gradient(linear, 0% 0%, 100% 0%, from(#AD7), to(#AD7), color-stop(0.2, #CEA), color-stop(0.45, #7A3), color-stop(0.55, #7A3));
}
Pseudo element
meter::-webkit-meter-vertical-suboptimal-value {
-webkit-appearance: meter;
background: -webkit-gradient(linear, 0% 0%, 100% 0%, from(#FE7), to(#FE7), color-stop(0.2, #FFC), color-stop(0.45, #DB3), color-stop(0.55, #DB3));
}
Pseudo element
meter::-webkit-meter-vertical-even-less-good-value {
-webkit-appearance: meter;
background: -webkit-gradient(linear, 0% 0%, 100% 0%, from(#F77), to(#F77), color-stop(0.2, #FCC), color-stop(0.45, #D44), color-stop(0.55, #D44));
}
Where can I find the right CSS properties for gecko-based browsers (Firefox), Opera and IE?
Here is a cross browser solution in 2019:
meter {
--background: #dadada;
--optimum: forestgreen;
--sub-optimum: gold;
--sub-sub-optimum: crimson;
/* The gray background in Firefox */
background: var(--background);
display: block;
margin-bottom: 1em;
width: 100%;
}
/* The gray background in Chrome, etc. */
meter::-webkit-meter-bar {
background: var(--background);
}
/* The green (optimum) bar in Firefox */
meter:-moz-meter-optimum::-moz-meter-bar {
background: var(--optimum);
}
/* The green (optimum) bar in Chrome etc. */
meter::-webkit-meter-optimum-value {
background: var(--optimum);
}
/* The yellow (sub-optimum) bar in Firefox */
meter:-moz-meter-sub-optimum::-moz-meter-bar {
background: var(--sub-optimum);
}
/* The yellow (sub-optimum) bar in Chrome etc. */
meter::-webkit-meter-suboptimum-value {
background: var(--sub-optimum);
}
/* The red (even less good) bar in Firefox */
meter:-moz-meter-sub-sub-optimum::-moz-meter-bar {
background: var(--sub-sub-optimum);
}
/* The red (even less good) bar in Chrome etc. */
meter::-webkit-meter-even-less-good-value {
background: var(--sub-sub-optimum);
}
<label>
Optimum
<meter value=80 min=0 low=30 high=60 max=100 optimum=80>
80/100
</meter>
</label>
<label>
Sub-optimum
<meter value=80 min=0 low=30 high=60 max=100 optimum=50>
80/100
</meter>
</label>
<label>
Sub-sub-optimum
<meter value=80 min=0 low=30 high=60 max=100 optimum=20>
80/100
</meter>
</label>
Note that the unfilled (grey) portion of the meter is styled with the ::-webkit-meter-bar in Chrome, while firefox uses ::-moz-meter-bar for the filled (green, yellow, red) part and styles the unfilled part with under the meter element it self.
Also note that firefox has pseudo selectors on the meter element to differentiate between optimal and sub-optimal values (:-moz-optimal, :-moz-sub-optimal, and :-moz-sub-sub-optimal; then you simply style the ::-moz-meter-bar pseudo child of the appropriate pseudo selector) while Chrome allows you to style different pseudo elements for that purpose (::-webkit-meter-optimum-value, ::-webkit-meter-suboptimum-value, and ::-webkit-meter-even-less-good-value respectively).
Here is a link that explains what these prefixed pseudo elements mean.
https://scottaohara.github.io/a11y_styled_form_controls/src/meter/
I got the meter styled with a nice subtle gradient in Webkit browsers using the following code:
meter { -webkit-appearance: none; } //Crucial, this will disable the default styling in Webkit browsers
meter::-webkit-meter-bar {
background: #FFF;
border: 1px solid #CCC;
}
meter::-webkit-meter-optimum-value {
background: #87C7DE;
background: -moz-linear-gradient(top, #a1d4e6 0%, #6bb4d1 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #a1d4e6), color-stop(100%, #6bb4d1));
background: -webkit-linear-gradient(top, #a1d4e6 0%, #6bb4d1 100%);
background: -o-linear-gradient(top, #a1d4e6 0%, #6bb4d1 100%);
background: -ms-linear-gradient(top, #a1d4e6 0%, #6bb4d1 100%);
background: linear-gradient(to bottom, #a1d4e6 0%, #6bb4d1 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#a1d4e6', endColorstr='#6bb4d1',GradientType=0);
}
However, Chris Coyier over at CSS-Tricks recommends the following HTML code:
<div class="meter">
<span style="width: 25%"></span>
</div>
... rather than the HTML5 <meter> or <progress> tags. At this point in time (February 2013), I agree with him:
To make things worse, things are very different across browsers, even
between different WebKit browsers. Pseudo elements also work
inconsistently. I hate to leave things hanging like this, but this is
really a topic for another time. Suffice it to say, for these
particular progress bars, the div/span thing is the ticket for now.
Browsers just don't really seem ready to accept the new HTML5 standard tags for <meter> and <progress>. With that said, I'd suggest that people get over the desire to go straight for the future and rather go for something that works visually until further notice. I should also mention that at the current point in time, the current browser support for these tags is at 53%... that's not worth it for me, but I'll leave that to your project's discretion.
Below are the rules for FireFox. I included a screenshot on where to find the rules in the Firefox inspector.
::-moz-meter-bar {
/* Block styles that would change the type of frame we construct. */
display: inline-block ! important;
float: none ! important;
position: static ! important;
overflow: visible ! important;
-moz-appearance: meterchunk;
height: 100%;
width: 100%;
}
:-moz-meter-optimum::-moz-meter-bar {
/* green. */
background: -moz-linear-gradient(top, #ad7, #ad7, #cea 20%, #7a3 45%, #7a3 55%);
}
:-moz-meter-sub-optimum::-moz-meter-bar {
/* orange. */
background: -moz-linear-gradient(top, #fe7, #fe7, #ffc 20%, #db3 45%, #db3 55%);
}
:-moz-meter-sub-sub-optimum::-moz-meter-bar {
/* red. */
background: -moz-linear-gradient(top, #f77, #f77, #fcc 20%, #d44 45%, #d44 55%);
}
Meter elements look like progress bars used elsewhere on the platform you are on.
try this to replace the meter elements:
<div style="padding:2px;background:#CCC;">
<div style="width:25%;background:#F00;text-align:center;">
<span>25%</span>
</div>
</div>
For anyone looking for a non-trivial style in 2021, it's certainly possible to create any kind of meter you want through creative use of the background-image property and friends.
The only difference between firefox and chrome is the background: none;
Safari requires -webkit-appearance: none, while Chrome requires -webkit-appearance: meter, so they are incompatible. The hack to make this work is out of scope for this answer.
.scaffolding {
display: grid;
grid-template-columns: 2rem 1fr;
gap: 8px;
}
label {
display: flex;
align-items: center;
justify-content: flex-end;
line-height: 0;
}
meter,
meter::-webkit-meter-bar,
meter::-webkit-meter-optimum-value,
meter::-webkit-meter-suboptimum-value,
meter::-webkit-meter-even-less-good-value,
meter::-webkit-meter-inner-element {
background: none;
border-radius: 0;
border: none;
width: 100%;
height: 4rem;
}
meter {
appearance: none;
-moz-appearance: meter;
-webkit-appearance: meter;
width: 20rem; //very important
}
meter::-webkit-meter-optimum-value {
background-image: repeating-linear-gradient(to right,
transparent 0rem, transparent 0.25rem,
green 0.25rem, green 0.5rem, transparent 0.5rem, transparent 0.75rem,
green 0.75rem, green 1rem, transparent 1rem, transparent 1.25rem,
green 1.25rem, green 1.5rem, transparent 1.5rem, transparent 1.75rem,
green 1.75rem, green 2rem, transparent 2rem, transparent 2.25rem),
repeating-linear-gradient(to right,
transparent 0%, transparent 2.25rem, green 2.25rem, green 2.5rem, transparent 2.5rem);
background-size: 2.5rem 3rem, 2.5rem 4rem;
background-position-y: center, center;
background-repeat: repeat-x, repeat-x;
}
meter::-moz-meter-bar {
background: none;
background-image: repeating-linear-gradient(to right,
transparent 0rem, transparent 0.25rem,
green 0.25rem, green 0.5rem, transparent 0.5rem, transparent 0.75rem,
green 0.75rem, green 1rem, transparent 1rem, transparent 1.25rem,
green 1.25rem, green 1.5rem, transparent 1.5rem, transparent 1.75rem,
green 1.75rem, green 2rem, transparent 2rem, transparent 2.25rem),
repeating-linear-gradient(to right,
transparent 0%, transparent 2.25rem, green 2.25rem, green 2.5rem, transparent 2.5rem);
background-size: 2.5rem 3rem, 2.5rem 4rem;
background-position-y: center, center;
background-repeat: repeat-x, repeat-x;
}
<div class="scaffolding">
<label>40</label>
<meter min="0" max="40" value="40"></meter>
<label>20</label>
<meter min="0" max="40" value="20"></meter>
<label>15</label>
<meter min="0" max="40" value="15"></meter>
<label>35</label>
<meter min="0" max="40" value="35"></meter>
<label>4</label>
<meter min="0" max="40" value="4"></meter>
</div>
You can style the meter size and position using something like the following in your css:
meter {
margin: 0 auto 4.5em;
width: 450px;
height: 50px;
display: block;
}
For colours, you need to use a webkit appropriate to your browser.