1
body {
  margin: 0;
  padding: 0;
  background: linear-gradient(180deg, #2a5470 25%, #4c4177 100%);
}

.border {
  padding: 10px;
  border-radius: 20px;
  background-image: linear-gradient(25deg, #2a5470 25%, #4c4177 100%);
}
.clock {
  display: flex;
  flex-direction: column;
  align-items: center;
  background: linear-gradient(180deg, #2a5470 25%, #4c4177 100%); //How do i make it continue gradient of body?
  border-radius: 20px;
}

<body>
<div class="border">
  <div class="clock">
    <h2>Break/Session</h2>
    <div>25:00</div>
  </div>
</div>
</body>

Here's how it looks now

In order to make the border have gradient, i found out that i need to make separate div with background as this gradient and then adjust padding. What i want to achieve is to make .clock background continue gradient of the body, just like it would without having .border around it.

  • in the duplicate you will find answers with transparency so you don't need to bother with the background behind – Temani Afif Feb 06 '23 at 20:54

2 Answers2

0

Just take the gradient property outside and add the class names generally as listed below,

body {
  margin: 0;
  padding: 0;
  background-repeat: no-repeat;
  min-height: 100vh;
}

body,.clock {
background: linear-gradient(180deg, #2a5470 25%, #4c4177 100%);
}

.border {
  padding: 10px;
    border-radius: 20px;
    background-image: linear-gradient(25deg, #2a5470 25%, #4c4177 100%);
    max-width: 200px;
    margin: 50px auto 0;
}
.clock {
  display: flex;
  flex-direction: column;
  align-items: center;
  border-radius: 20px;
}
h2, .clock div {
    color: #fff;
}

.clock div {
    font-size: 50px;
}
<body>
<div class="border">
  <div class="clock">
    <h2>Break/Session</h2>
    <div>25:00</div>
  </div>
</div>
</body>
Nikesh Kp
  • 374
  • 1
  • 7
  • that will redo the background again as in OPs original question and doesn't achieve what they're looking for: something that basically looks as if only the border had a different gradient and the clock itself has no background at all. – Plagiatus Feb 06 '23 at 12:04
-1

Here is an idea on how to achieve this. Using nested divs like in your example might not be the easiest solution through, as you'd probably need to overwrite the inner divs background with some js obtained values, as there is no easy way to reset the background like that.

Edit: See this question for a better solution using just CSS: Border Gradient with Border Radius.
Scroll down for a JS solution.

Using css only with border-image

Answer taken from https://css-tricks.com/gradient-borders-in-css/ and adapted.

You can use the border-image css attribute to more easily achieve what you're looking for, if you don't need a border-radius.

I'm just using the wrapper here to increase the viewport of the example.

body {
  margin: 0;
  padding: 0;
  background: linear-gradient(180deg, #2a5470 25%, #4c4177 100%);
}

.clock {
  display: flex;
  flex-direction: column;
  align-items: center;
  border: 15px solid;
  border-image-source: linear-gradient(25deg, #2a5470 25%, #4c4177 100%);
  border-image-slice: 1;
}

.wrapper {
  height: 200px;
}
<body>
  <div class="wrapper">
    <div class="clock">
      <h2>Break/Session</h2>
      <div>25:00</div>
    </div>
  </div>
</body>

Using JS for an actually working solution

The idea here is that you can manually calculate the position of the clock inside the body element and set the background manually. This solution I present below is specifically tailored for this specific background and assumes things like "it will only ever be inside the parent element and never move outside". A more general solution would need to be much more extensive, but I hope it gets my idea across.

// update the background when scrolling
window.addEventListener("scroll", updateBackgroundColor);

const wrapper = document.querySelector("body");
const clock = document.querySelector(".clock");

function updateBackgroundColor(){
    const wrapperRect = wrapper.getBoundingClientRect();
    const clockRect = clock.getBoundingClientRect();
    // in this case we only care about top and bottom, because the gradient is a straight 180°.
    // so we get the relative position inside the outer relevant element
    const relativePosition = {
        top: (clockRect.top - wrapperRect.top) / wrapperRect.height,
        bottom: (clockRect.top + clockRect.height - wrapperRect.top) / wrapperRect.height,
    }
    
    // since the gradient only starts at 25% down, we need to adjust the calculation to use those relative values instead
    const startPercentage = 0.25;
    // this math is just a fancy way of saying "(top - 0.25) * (4/3)" because that is what scales the values for us to the desired range.
    relativePosition.top = (relativePosition.top - startPercentage) * ((1 / startPercentage) / ((1 - startPercentage) / startPercentage));
    relativePosition.bottom = (relativePosition.bottom - startPercentage) * ((1 / startPercentage) / ((1 - startPercentage) / startPercentage));
    // if value is negative, set to 0
    if(relativePosition.top < 0) relativePosition.top = 0;
    if(relativePosition.bottom < 0) relativePosition.bottom = 0;
    
    let newTopColor = getGradientColor({r:42, g:84, b:112} /*#2a5470*/, {r:76, g:65, b:119} /*#4c4177*/, relativePosition.top);
    let newBottomColor = getGradientColor({r:42, g:84, b:112} /*#2a5470*/, {r:76, g:65, b:119} /*#4c4177*/, relativePosition.bottom);
    
    clock.style.background = `linear-gradient(180deg, rgb(${newTopColor.r}, ${newTopColor.g}, ${newTopColor.b}) 0%, rgb(${newBottomColor.r}, ${newBottomColor.g}, ${newBottomColor.b}) 100%)`;
}

// returns the linearly interpolated gradient color value between two colors
// colors are represented as {r:, g:, b:} objects for simplicity
function getGradientColor(color1, color2, percentage){
    return {
        r: color1.r + ((color2.r - color1.r) * percentage),
        g: color1.g + ((color2.g - color1.g) * percentage),
        b: color1.b + ((color2.b - color1.b) * percentage),
    }
}

// run once so it works immediately not just after the first scrolling
updateBackgroundColor();
body {
  margin: 0;
  padding: 0;
  background-repeat: no-repeat;
  min-height: 200vh;
}

body, .clock {
  background: linear-gradient(180deg, #2a5470 25%, #4c4177 100%);
}

.border {
  padding: 10px;
  border-radius: 20px;
  background-image: linear-gradient(25deg, #2a5470 25%, #4c4177 100%);
  max-width: 200px;
  margin: 50px auto 0;
  position: sticky;
  top: 10px;
}
.clock {
  display: flex;
  flex-direction: column;
  align-items: center;
  border-radius: 20px;
}
h2, .clock div {
  color: #fff;
}

.clock div {
  font-size: 50px;
}
<!DOCTYPE html>
<html>
<body>
  <div class="border">
    <div class="clock">
      <h2>Break/Session</h2>
      <div>25:00</div>
    </div>
  </div>
</body>
</html>
Plagiatus
  • 360
  • 2
  • 12
  • In this case .clock inherits the background from .border, but i want it to inherit the background from body, specifically to continue the gradient pattern. Final look i'm trying to achieve is only to have .border be a different gradient, while body and .clock are the same gradient (the same meaning .clock is continuing body's gradient pattern, not just having the same gradient started from scratch, like it is now in the code i provided). – stilltrillogf Feb 06 '23 at 11:33
  • alright, I see. I've updated my answer to take a different approach to solve your issue. :) – Plagiatus Feb 06 '23 at 12:02
  • I've stumbled upon this solution, the thing is that I need a border radius. Probably will end up using different design, but out of curiosity, how would you solve this using js? – stilltrillogf Feb 06 '23 at 14:43
  • @stilltrillogf I've updated my answer to include my JS idea. The gist of it is that you can calculate the position of the clock inside the body and adjust the background colors accordingly. – Plagiatus Feb 08 '23 at 08:57