A Pen by Bryan C Guner on CodePen.
Created
August 15, 2022 18:30
-
-
Save bgoonz/2aea9e758c74e32d70202748095cdf72 to your computer and use it in GitHub Desktop.
Dashed Border Generator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="content"> | |
<h2>Dashed border using <span>background-image</span> property</h2> | |
<p> | |
Creating dashed borders with background-image is not a new concept. Many people use it because it allows full flexibility, and with a little creativity (and a few lines of code) it is possible to do cool things without it being too complicated. | |
</p> | |
<div class="boxes"> | |
<div class="box box-a">Simple</div> | |
<div class="box box-b">Slanted</div> | |
<div class="box box-c">Dotted</div> | |
<div class="box box-d">Long</div> | |
<div class="box box-e">Cornered</div> | |
<div class="box box-f">Centered</div> | |
<div class="box box-g">Faded</div> | |
<div class="box box-h">Animated</div> | |
</div> | |
<hr> | |
<h2>Create your own <span>background-image</span> border</h2> | |
<div class="generator"> | |
<form> | |
<Label> | |
Border width | |
<input name="borderWidth" type="range" class="input" min="1" max="10" value="3"> | |
</Label> | |
<Label> | |
Border color<br> | |
<input name="borderColor" type="color" class="input" value="#333333"> | |
</Label> | |
<Label> | |
Dash length | |
<input name="dashLength" type="range" class="input" min="1" max="30" value="10"> | |
</Label> | |
<Label> | |
Spacing | |
<input name="spacing" type="range" class="input" min="1" max="30" value="10"> | |
</Label> | |
<Label> | |
Slanting angle | |
<input name="slanting" type="range" class="input" min="-60" max="60" value="0"> | |
</Label> | |
<Label> | |
Fade | |
<input name="borderFade" type="range" class="input" min="0" max="100" value="0"> | |
</Label> | |
<Label> | |
<input name="diraction" type="checkbox"> | |
Flip diraction | |
</Label> | |
<Label> | |
Animation | |
<input name="animation" type="range" class="input" min="0" max="1" step="0.1" value="0"> | |
</Label> | |
</form> | |
<div class="result"></div> | |
</div> | |
</div> | |
<a href="https://twitter.com/bgooonz" class="twitterLink" target="_blank"> | |
<img src="https://assets.codepen.io/1948355/twitterLogo2.png" /> | |
</a> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function _(e, all=false) { | |
let divs = document.querySelectorAll(e); | |
if (all || (divs.length > 1)) { return divs; } | |
return divs[0]; | |
} | |
_('input', true).forEach(element => { | |
element.addEventListener('input', drawBordr); | |
}); | |
const resultDiv = _('.result'); | |
drawBordr(); | |
function drawBordr() { | |
let borderWidth = Number(_('[name="borderWidth"]').value); | |
let color1 = _('[name="borderColor"]').value; | |
let dashLength = Number(_('[name="dashLength"]').value); | |
let spacing = Number(_('[name="spacing"]').value); | |
let slanting = Number(_('[name="slanting"]').value); | |
let borderFade = 100 - Number(_('[name="borderFade"]').value); | |
let diraction = _('[name="diraction"]').checked; | |
let animation = Number(_('[name="animation"]').value); | |
let color2 = 'transparent'; | |
const backgroundImage = ` | |
repeating-linear-gradient(${slanting + (diraction ? 180 : 0) }deg, ${color1}, ${color1} ${Math.round(dashLength * borderFade) / 100}px, ${color2} ${dashLength}px, ${color2} ${dashLength + (Math.round(spacing * borderFade) / 100)}px, ${color1} ${dashLength + spacing}px), | |
repeating-linear-gradient(${slanting + (diraction ? 270 : 90)}deg, ${color1}, ${color1} ${Math.round(dashLength * borderFade) / 100}px, ${color2} ${dashLength}px, ${color2} ${dashLength + (Math.round(spacing * borderFade) / 100)}px, ${color1} ${dashLength + spacing}px), | |
repeating-linear-gradient(${slanting + (diraction ? 0 : 180) }deg, ${color1}, ${color1} ${Math.round(dashLength * borderFade) / 100}px, ${color2} ${dashLength}px, ${color2} ${dashLength + (Math.round(spacing * borderFade) / 100)}px, ${color1} ${dashLength + spacing}px), | |
repeating-linear-gradient(${slanting + (diraction ? 90 : 270)}deg, ${color1}, ${color1} ${Math.round(dashLength * borderFade) / 100}px, ${color2} ${dashLength}px, ${color2} ${dashLength + (Math.round(spacing * borderFade) / 100)}px, ${color1} ${dashLength + spacing}px)`; | |
const borderLengthPx = Math.round((dashLength + spacing) / Math.sin((90 - Math.abs(slanting)) * Math.PI / 180) * 100) / 100; | |
const borderLength = (animation > 0) ? `calc(100% + ${borderLengthPx}px)` : '100%'; | |
const backgroundSize = `${borderWidth}px ${borderLength}, ${borderLength} ${borderWidth}px, ${borderWidth}px ${borderLength} , ${borderLength} ${borderWidth}px`; | |
const backgroundPosition = `0 0, 0 0, 100% 0, 0 100%`; | |
resultDiv.style.backgroundImage = backgroundImage; | |
resultDiv.style.backgroundSize = backgroundSize; | |
resultDiv.style.backgroundPosition = backgroundPosition; | |
const animationPropery = (animation > 0) ? `borderAnimation ${Math.round((1.1 - animation) * 10) / 10}s infinite linear${diraction ? ' reverse' : ''}` : 'unset'; | |
resultDiv.style.animation = animationPropery; | |
let animationTxt = ''; | |
if (animation > 0) { | |
document.documentElement.style.setProperty('--AnimationLength', `-${borderLengthPx}px`); | |
animationTxt = ` | |
<span><b>animation:</b> ${animationPropery};</span> | |
}<br> | |
<br> | |
@keyframes <b>borderAnimation</b> { | |
<span>from { background-position: 0 0, -${borderLengthPx}px 0, 100% -${borderLengthPx}px, 0 100%; }</span> | |
<span>to { background-position: 0 -${borderLengthPx}px, 0 0, 100% 0, -${borderLengthPx}px 100%; }</span> | |
`; | |
} | |
resultDiv.style.padding = `calc(1em + ${borderWidth}px)`; | |
resultDiv.innerHTML = ` | |
<code> | |
.box { | |
<span><b>background-image:</b> ${backgroundImage};</span> | |
<span><b>background-size:</b> ${backgroundSize};</span> | |
<span><b>background-position:</b> ${backgroundPosition};</span> | |
<span><b>background-repeat:</b> no-repeat; </span> | |
${animationTxt} | |
} | |
</code> | |
`; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@import url('https://fonts.googleapis.com/css2?family=Open+Sans+Condensed:wght@300;700&display=swap'); | |
*, *::before, *::after { | |
padding: 0; | |
margin: 0 auto; | |
box-sizing: border-box; | |
} | |
body { | |
font-family: 'Open Sans Condensed', sans-serif; | |
min-height: 100vh; | |
background-color: #eee; | |
background-size: 10px 10px; | |
background-image: | |
radial-gradient(circle at 50% 50%, #ddd, #ddd 1px, transparent 1px), | |
radial-gradient(circle at 0 0, #ddd, #ddd 1px, transparent 1px), | |
radial-gradient(circle at 0 100%, #ddd, #ddd 1px, transparent 1px), | |
radial-gradient(circle at 100% 0, #ddd, #ddd 1px, transparent 1px), | |
radial-gradient(circle at 100% 100%, #ddd, #ddd 1px, transparent 1px); | |
color: #333; | |
} | |
:root { | |
--clr-border: #333; | |
--AnimationLength: 0px; | |
} | |
.content { | |
width: 100%; max-width: 960px; | |
padding: 2em 2em 10em; | |
} | |
h2 { | |
margin: 1em auto; | |
text-decoration: underline; | |
text-decoration-color: #aaa; | |
& span { | |
color: #777; | |
} | |
} | |
p { | |
margin: 2em auto; | |
font-weight: bold; | |
} | |
hr { | |
height: 3px; | |
border: none; | |
margin: 4em auto; | |
background-color: #aaa; | |
} | |
.boxes { | |
width: 100%; | |
display: grid; | |
grid-gap: 2em; | |
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); | |
} | |
.box { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
width: 100%; height: 123px; | |
font-size: 2em; | |
padding: 0.5em; | |
line-height: 1; | |
background-position: 0 0, 0 0, 100% 0, 0 100%; | |
background-size: 3px 100%, 100% 3px, 3px 100% , 100% 3px; | |
background-repeat: no-repeat; | |
} | |
.box-a { // Simple | |
background-image: | |
repeating-linear-gradient(0deg, var(--clr-border), var(--clr-border) 10px, transparent 10px, transparent 20px), // left | |
repeating-linear-gradient(90deg, var(--clr-border), var(--clr-border) 10px, transparent 10px, transparent 20px), // top | |
repeating-linear-gradient(180deg, var(--clr-border), var(--clr-border) 10px, transparent 10px, transparent 20px), // right | |
repeating-linear-gradient(270deg, var(--clr-border), var(--clr-border) 10px, transparent 10px, transparent 20px) // bottom | |
; | |
border-image: repeating-linear-gradient(0deg, var(--clr-border), var(--clr-border) 10px, transparent 10px, transparent 20px); | |
} | |
.box-b { // Slanted | |
background-image: | |
repeating-linear-gradient(45deg, var(--clr-border), var(--clr-border) 10px, transparent 10px, transparent 20px), // left | |
repeating-linear-gradient(135deg, var(--clr-border), var(--clr-border) 10px, transparent 10px, transparent 20px), // top | |
repeating-linear-gradient(225deg, var(--clr-border), var(--clr-border) 10px, transparent 10px, transparent 20px), // right | |
repeating-linear-gradient(315deg, var(--clr-border), var(--clr-border) 10px, transparent 10px, transparent 20px) // bottom | |
; | |
} | |
.box-c { // Dotted | |
background-image: | |
repeating-linear-gradient(0deg, var(--clr-border), var(--clr-border) 3px, transparent 3px, transparent 6px), // left | |
repeating-linear-gradient(90deg, var(--clr-border), var(--clr-border) 3px, transparent 3px, transparent 6px), // top | |
repeating-linear-gradient(180deg, var(--clr-border), var(--clr-border) 3px, transparent 3px, transparent 6px), // right | |
repeating-linear-gradient(270deg, var(--clr-border), var(--clr-border) 3px, transparent 3px, transparent 6px) // bottom | |
; | |
} | |
.box-d { // Long | |
background-image: | |
repeating-linear-gradient(0deg, var(--clr-border), var(--clr-border) 30px, transparent 30px, transparent 36px), // left | |
repeating-linear-gradient(90deg, var(--clr-border), var(--clr-border) 30px, transparent 30px, transparent 36px), // top | |
repeating-linear-gradient(180deg, var(--clr-border), var(--clr-border) 30px, transparent 30px, transparent 36px), // right | |
repeating-linear-gradient(270deg, var(--clr-border), var(--clr-border) 30px, transparent 30px, transparent 36px) // bottom | |
; | |
} | |
.box-e { // Cornered | |
background-image: | |
linear-gradient(0deg, var(--clr-border), var(--clr-border) 25%, transparent 25%, transparent 75%, var(--clr-border) 75%), // left | |
linear-gradient(90deg, var(--clr-border), var(--clr-border) 25%, transparent 25%, transparent 75%, var(--clr-border) 75%), // top | |
linear-gradient(180deg, var(--clr-border), var(--clr-border) 25%, transparent 25%, transparent 75%, var(--clr-border) 75%), // right | |
linear-gradient(270deg, var(--clr-border), var(--clr-border) 25%, transparent 25%, transparent 75%, var(--clr-border) 75%) // bottom | |
; | |
} | |
.box-f { // Centered | |
background-image: | |
linear-gradient(0deg, transparent 15%, var(--clr-border) 15%, var(--clr-border) 85%, transparent 85%), // left | |
linear-gradient(90deg, transparent 15%, var(--clr-border) 15%, var(--clr-border) 85%, transparent 85%), // top | |
linear-gradient(180deg, transparent 15%, var(--clr-border) 15%, var(--clr-border) 85%, transparent 85%), // right | |
linear-gradient(270deg, transparent 15%, var(--clr-border) 15%, var(--clr-border) 85%, transparent 85%) // bottom | |
; | |
} | |
.box-g { // Faded | |
background-image: | |
repeating-linear-gradient(0deg, var(--clr-border), var(--clr-border) 10px, transparent 20px, transparent 30px, var(--clr-border) 40px), // left | |
repeating-linear-gradient(90deg, var(--clr-border), var(--clr-border) 10px, transparent 20px, transparent 30px, var(--clr-border) 40px), // top | |
repeating-linear-gradient(180deg, var(--clr-border), var(--clr-border) 10px, transparent 20px, transparent 30px, var(--clr-border) 40px), // right | |
repeating-linear-gradient(270deg, var(--clr-border), var(--clr-border) 10px, transparent 20px, transparent 30px, var(--clr-border) 40px) // bottom | |
; | |
} | |
.box-h { // Animated | |
background-image: | |
repeating-linear-gradient(0deg, var(--clr-border), var(--clr-border) 10px, transparent 10px, transparent 20px), // left | |
repeating-linear-gradient(90deg, var(--clr-border), var(--clr-border) 10px, transparent 10px, transparent 20px), // top | |
repeating-linear-gradient(180deg, var(--clr-border), var(--clr-border) 10px, transparent 10px, transparent 20px), // right | |
repeating-linear-gradient(270deg, var(--clr-border), var(--clr-border) 10px, transparent 10px, transparent 20px) // bottom | |
; | |
background-size: 3px calc(100% + 20px), calc(100% + 20px) 3px, 3px calc(100% + 20px) , calc(100% + 20px) 3px; | |
animation: boxBorderAnimation 1s infinite linear; | |
@keyframes boxBorderAnimation { | |
from { background-position: 0 0, -20px 0, 100% -20px, 0 100%; } | |
to { background-position: 0 -20px, 0 0, 100% 0, -20px 100%; } | |
} | |
} | |
// Generator: | |
.generator { | |
display: grid; | |
grid-template-columns: repeat(2, 1fr); | |
grid-gap: 3em; | |
@media (max-width: 768px) { | |
grid-template-columns: 1fr; | |
} | |
} | |
form { | |
width: 100%; | |
label { | |
display: block; | |
font-weight: bold; | |
width: 100%; | |
& + label { | |
margin-top: 1.5em; | |
} | |
} | |
.input { | |
display: block; | |
width: 100%; | |
} | |
} | |
.result { | |
width: 100%; | |
height: 100%; | |
padding: 1em; | |
line-height: 1.2; | |
background-repeat: no-repeat; | |
span { | |
display: block; | |
padding-left: 4em; | |
text-indent: -2em; | |
margin: 0.5em auto; | |
} | |
@keyframes borderAnimation { | |
from { background-position: 0 0, var(--AnimationLength) 0, 100% var(--AnimationLength), 0 100%; } | |
to { background-position: 0 var(--AnimationLength), 0 0, 100% 0, var(--AnimationLength) 100%; } | |
} | |
} | |
.twitterLink { | |
position: fixed; | |
bottom: 0.5em; right: 0.5em; | |
& img { | |
width: 2em; | |
filter: grayscale(100%); | |
transition: filter 0.25s; | |
&:hover { | |
filter: grayscale(0%); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment