Search code examples
htmlcssfrontendcss-grid

Making CSS cards slightly transparent


I want to make something like this: enter image description here

As you can see, the adjacent borders in the center are slightly darker than other parts. How to make it with CSS?


Solution

  • Updated # 2023-08-22

    It seemed like a good idea to illustrate the animation as well. My original response can be read below.

    It's quite simple. We set up a listener for mouse movement events using JavaScript. When this happens, we adjust the position of the .blob class based on the position of the .fakeblob (fixed position) class and the current cursor position. This way, as you move the mouse cursor, a faint circle follows along on the cards. By using CSS z-index settings, we ensure that the circle is only visible within the cards. Have fun experimenting with the pattern!

    The idea was inspired by the code of "yxsh".

    const all = document.querySelectorAll(".grid > div");
    
    /* event listener for mouse moving */
    window.addEventListener("mousemove", (ev) => {
      /* set blob on all elements */
      all.forEach((e) => {
        const blob = e.querySelector(".blob");
        const fakeblob = e.querySelector(".fakeblob");
        const rec = fakeblob.getBoundingClientRect();
        blob.style.opacity = "1";
      
        blob.animate([{
          transform: `translate(
            ${(ev.clientX - rec.left) - (rec.width / 2)}px,
            ${(ev.clientY - rec.top) - (rec.height / 2)}px
          )`
        }], {
          duration: 300,
          fill: "forwards"
        });
      });
    });
    :root {
      /* to animation */
      --blob-color: rgb(255, 255, 255, 0.5);
      --blob-size: 123px;
      --blob-strong: 30px; /* circle: 30+ px, square: 0 */
      --blob-radius: 20%; /* circle: 50%, square: 0 */
    }
    
    /* grid */
    .grid {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      grid-gap: 20px;
      padding: 20px;
      box-sizing: border-box;
      width: 500px;
      height: 300px;
      background-image: url(https://i.sstatic.net/QYZq3.png);
      background-size: cover;
      background-repeat: no-repeat;
      background-position: center;
    }
    
    /* element */
    .grid > div {
      position: relative; /* <--- to animation */
      overflow: hidden;
      padding: 3px;
      margin: 0;
    }
    
    /* element parts: inner, blob, fakeblob */
    
    /* inner: to readable content */
    .grid > div > .inner {
      position: relative;
      z-index: 1;
      padding: 10px;
      width: 210px;
      height: 150px;
      color: white;
      backdrop-filter: blur(1px); /* <--- to readable text */
    }
    
    /* blob: to animation */
    .grid > div > .blob {
      filter: blur(var(--blob-strong));
      position: absolute;
      z-index: 0;
      top: 0;
      opacity: 0;
      left: 0;
      width: var(--blob-size);
      height: var(--blob-size);
      border-radius: var(--blob-radius);
      background: var(--blob-color);
    }
    
    /* fakeblob: to animation */
    .grid > div > .fakeblob {
      display: hidden;
      position: absolute;
      z-index: 0;
      top: 0;
      left: 0;
      width: calc(var(--blob-size) * 0.8);
      height: calc(var(--blob-size) * 0.8);
      border-radius: var(--blob-radius);
    }
    <div class="grid">
      <div>
        <div class="inner">Text Here</div>
        <div class="blob"></div>
        <div class="fakeblob"></div>
      </div>
      <div>
        <div class="inner">Text Here</div>
        <div class="blob"></div>
        <div class="fakeblob"></div>
      </div>
      <div>
        <div class="inner">Text Here</div>
        <div class="blob"></div>
        <div class="fakeblob"></div>
      </div>
      <div>
        <div class="inner">Text Here</div>
        <div class="blob"></div>
        <div class="fakeblob"></div>
      </div>
    </div>

    Original Answer

    Can use linear-gradient() or radial-gradient.

    To set a gradient background, you can use the background parameter. For a gradient border, you can use border-image-source.

    Your request wasn't very clear, but I assume you want to direct the endpoints of the four elements towards the center of the grid. In that case, I had to individually set the gradient for both the background and the border at each of the four elements to radiate in the desired direction.

    .grid {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      grid-gap: 20px;
      padding: 20px;
      box-sizing: border-box;
      width: 500px;
      height: 300px;
      background-image: url(https://i.sstatic.net/QYZq3.png);
      background-size: cover;
      background-repeat: no-repeat;
      background-position: center;
    }
    
    .grid div {
      background-color: rgba(255, 255, 255, 0.1); /* if linear-gradient() not working on browser */
      border-width: 1px;
      border-style: solid;
      border-image-slice: 1;
      height: 100%;
      width: 100%;
    }
    
    .grid div:nth-child(1) {
      background: linear-gradient(to bottom right, rgba(255, 255, 255, 0.0) 50%, rgba(255, 255, 255, 0.4) 100%);
      border-top-width: 0;
      border-left-width: 0;
      border-image-source: linear-gradient(to bottom right, rgba(255, 255, 255, 0.0) 50%, rgba(255, 255, 255, 0.8) 100%);
    }
    .grid div:nth-child(2) {
      background: linear-gradient(to bottom left, rgba(255, 255, 255, 0.0) 50%, rgba(255, 255, 255, 0.4) 100%);
      border-top-width: 0;
      border-right-width: 0;
      border-image-source: linear-gradient(to bottom left, rgba(255, 255, 255, 0.0) 50%, rgba(255, 255, 255, 0.8) 100%);
    }
    .grid div:nth-child(3) {
      background: linear-gradient(to top right, rgba(255, 255, 255, 0.0) 50%, rgba(255, 255, 255, 0.4) 100%);
      border-bottom-width: 0;
      border-left-width: 0;
      border-image-source: linear-gradient(to top right, rgba(255, 255, 255, 0.0) 50%, rgba(255, 255, 255, 0.8) 100%);
    }
    .grid div:nth-child(4) {
      background: linear-gradient(to top left, rgba(255, 255, 255, 0.0) 50%, rgba(255, 255, 255, 0.4) 100%);
      border-bottom-width: 0;
      border-right-width: 0;
      border-image-source: linear-gradient(to top left, rgba(255, 255, 255, 0.0) 50%, rgba(255, 255, 255, 0.8) 100%);
    }
    <div class="grid">
      <div></div>
      <div></div>
      <div></div>
      <div></div>
    </div>