Reputation: 1
I want to create an animated border for two elements, one which displays colour on the border, and one which displays grayscale on the border.
The grayscale needs to be applied to only the border however, not the entire image. So the image is still in full colour, however the border animates smoothly just in grayscale.
I'm stuck on how to do this, can anyone help?
I have used filter:grayscale however I don't know if there is a way to apply this just to the border, or if I need to change the strcuture of my HTML, and apply different CSS to it?
Here is my Code:
@property --bg-angle {
inherits: false;
initial-value: 0deg;
syntax: "<angle>";
}
@keyframes spin {
to {
--bg-angle: 360deg;
}
}
.scale-up {
text-align: center;
}
.scale-up .animated-border {
transition: ease-in-out 0.2s;
animation: spin 3s infinite linear paused;
background: linear-gradient(
to bottom,
oklch(0.1 0.2 240 / 0.95),
oklch(0.1 0.2 240 / 0.95)
)
padding-box,
conic-gradient(
from var(--bg-angle) in oklch longer hue,
oklch(0.85 0.37 0) 0 0
)
border-box;
border: 2px solid transparent;
border-radius: 6px;
}
.scale-up .animated-border:hover {
transform: scale(1.05);
animation-play-state: running;
}
.scale-up .animated-border.mono {
filter: grayscale(100%);
}
.breaker {
font-size: 0;
height: 20px;
line-height: 0;
}
<div class="scale-up">
<a href="#" target="_blank">
<img src="https://placehold.co/1200x100/blue/white" class="animated-border mono" alt="Brother mono printers" style="width: 80%;">
</a>
</div>
<div class="breaker">
</div>
<div class="scale-up">
<a href="#" target="_blank"><img src="https://placehold.co/1200x100/blue/white" class="animated-border" alt="Brother Colour printers" style="width: 80%;">
</a>
</div>
and here is my link to my codepen: https://codepen.io/alexdjoelle/pen/azoPwdO
Upvotes: 0
Views: 85
Reputation: 34
Since CSS filters apply to the entire element (including content), you cannot directly apply grayscale only to the border without restructuring your HTML and CSS.
I would recommend you to restructure your HTML so that there is an extra div wrapper around the img and apply the grayscale effect only to the border you want to be grayscaled.
@property --bg-angle {
inherits: false;
initial-value: 0deg;
syntax: "<angle>";
}
@keyframes spin {
to {
--bg-angle: 360deg;
}
}
.scale-up {
text-align: center;
display: inline-block; /* Ensure it wraps around the content */
}
/* Wrapper with animated border */
.border-wrapper {
display: inline-block; /* Ensure wrapper only wraps the content */
border-radius: 6px;
padding: 2px;
/* Colorful background */
background: conic-gradient(
from var(--bg-angle),
#ff5733,
#ffbd33,
#33ff57,
#3357ff,
#a833ff,
#ff5733
);
animation: spin 3s infinite linear paused;
transition: transform 0.3s ease-in-out, animation 0.3s ease-in-out;
}
/* Inner image to avoid affecting content */
.border-wrapper img {
display: block;
border-radius: 6px;
width: 100%; /* Change this to your liking */
height: auto;
}
/* Grayscale effect for monochrome border */
.border-wrapper.mono {
filter: grayscale(100%);
}
.border-wrapper:hover {
transform: scale(1.05);
animation-play-state: running;
}
.breaker {
font-size: 0;
height: 20px;
line-height: 0;
}
<div class="scale-up">
<a href="#" target="_blank">
<div class="border-wrapper mono">
<img src="https://placehold.co/1200x100/blue/white" alt="Brother mono printers">
</div>
</a>
</div>
<div class="breaker"></div>
<div class="scale-up">
<a href="#" target="_blank">
<div class="border-wrapper">
<img src="https://placehold.co/1200x100/blue/white" alt="Brother Colour printers">
</div>
</a>
</div>
Here is a codepen link: https://codepen.io/ddk2231/pen/QwLzMON
Upvotes: 0
Reputation: 1
I'm still confused about the question, do you want one box with a full color border and another box with gray?
@property --bg-angle {
inherits: false;
initial-value: 0deg;
syntax: "<angle>";
}
@keyframes spin {
to {
--bg-angle: 360deg;
}
}
.scale-up {
text-align: center;
}
.scale-up-grey {
text-align: center;
}
.scale-up .animated-border {
transition: ease-in-out 0.2s;
animation: spin 3s infinite linear paused;
background: linear-gradient(
to bottom,
oklch(0.1 0.2 240 / 0.95),
oklch(0.1 0.2 240 / 0.95)
)
padding-box,
conic-gradient(
from var(--bg-angle) in oklch longer hue,
oklch(0.85 0.37 0) 0 0
)
border-box;
border: 2px solid transparent;
border-radius: 6px;
}
.scale-up-grey .animated-border {
transition: ease-in-out 0.2s;
animation: spin 3s infinite linear paused;
background: linear-gradient(90deg, rgba(2,0,36,1) 0%, rgba(0,0,0,0.8281687675070029) 35%, rgba(108,108,108,1) 100%);
border: 2px solid transparent;
border-radius: 6px;
}
.scale-up .animated-border:hover {
transform: scale(1.05);
animation-play-state: running;
}
.scale-up-grey .animated-border:hover {
transform: scale(1.05);
animation-play-state: running;
}
.breaker {
font-size: 0;
height: 20px;
line-height: 0;
}
<div class="scale-up-grey">
<a href="#" target="_blank">
<img src="https://placehold.co/1200x100/blue/white" class="animated-border mono" alt="Brother mono printers" style="width: 80%;">
</a>
</div>
<div class="breaker">
</div>
<div class="scale-up">
<a href="#" target="_blank"><img src="https://placehold.co/1200x100/blue/white" class="animated-border" alt="Brother Colour printers" style="width: 80%;">
</a>
</div>
Upvotes: 0
Reputation: 322
CSS does not support filter for border directly.
So Below is a simple solution with transition
.
Through transition: border
i only targed the border propertie.
div {
background-color: red;
padding: 1rem 2rem;
border: 5px solid black;
border-radius: 4px;
transition: border .5s ease;
}
div:hover {
border: 5px solid grey;
}
<div>
<p>
Hello World
<p>
</div>
Another way would be a pseudo element, but i dont really like working with pseudo elements.
div {
position: relative;
width: 100%;
height: auto;
background: #ff0000;
padding: 1rem 2rem;
border-radius: 4px;
}
div::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border: 5px solid #00ff00;
border-radius: 4px;
transition: filter 0.3s ease, border-color 0.3s ease;
}
div:hover::before {
filter: grayscale(100%);
border-color: #00ff00;
}
<div>
<p>
Hello World
</p>
</div>
Upvotes: 0