AlainIb
AlainIb

Reputation: 4728

css blend/blur/merge backgrounds images

I work on a website, this is just a demo here in ReactJS : https://poc-b-i-o-meteo.netlify.com/

The probleme is with the background.

The concept is easy, the app is composed with 4 parts, the top with meteo with no background and 3 parts each on with a different background. The app must be mobile & responsive, each part have different content so different height.

enter image description here

Now i want to make a nice effect between each part (météo & 1 ; 1&2; 2&3) like this :

enter image description here

So how to make each part to be over the bottom of the previous part for some pixel and to make it blend together nicely (like we can do with 2 png in photoshop with transparence ). This effect should be done in css because it should be there from mobile to wide screen.

Previously i tried :

  1. with 3 png who contained transparence, it doesn't work for two raison. PNG are SOOOOO heavy and it shown only a precise screen width.
  2. by adding a relative zone to bottom/top of the component Categorie with linear-gradient but render little ugly

1) APP.JS

import Meteo from "./components/Meteo";
import Categorie from "./components/Categorie";

function App() {
  return (
    <div className="App">
      <h5 style={{ paddingLeft: 15 }}>Météo</h5>
      <header className="App-header">
        <Meteo />
        <Categorie name="air" display="Air" bgpos="bottom" {/* bottomOpacity*/} />

        <Categorie name="sol" display="Sol" bgpos="center"  {/*  bottomOpacity topOpacity*/} />

        <Categorie name="eau" display="Eau" bgpos="top" {/* topOpacity */}/>

      </header>
    </div>
  );
}

2) Categorie.js

const useStyles = makeStyles(theme => ({
  root: {
    flexGrow: 1
  },
  leftText: {
    textAlign: "left",
    width: "auto",
    display: "inline-block"
  },
  responsive: {
    width: "100%",
    maxWidth: "1000px",
    height: "auto"
  },
  container: {
    display: "flex",
    flexDirection: "column",
    alignItems: "center",
    justifyContent: "center"
  },
  overlay: {
    backgroundColor: "rgba(13,53,78, 0.6)",

    color: "white",
    position: "relative"
  },

  topOpacity: {
    position: "absolute",
    top: -2,
    width: "100%",
    height: 75,
    background: "linear-gradient( to top, transparent , rgba(13,53,78,0.9 ) )",
    backgroundRepeat: "no-repeat"
  },
  bottomOpacity: {
    position: "absolute",
    bottom: -2,
    width: "100%",
    height: 75,
    background:
      "linear-gradient( to bottom, transparent , rgba(13,53,78, 0.9 ) )",
    backgroundRepeat: "no-repeat"
  },

  padding: {
    padding: "auto",
    paddingTop: 85,
    paddingBottom: 85
  }
}));

export default function Categorie(props) {
  const classes = useStyles();

  let ref = useRef(null);
  let size = useComponentSize(ref);
  let { width, height } = size;

  const filename = {
    air: "air.jpg",
    eau: "eau.jpg",
    sol: "sol.jpg"
  };

  let backgd = {
    backgroundImage: `url('./photos/${filename[props.name]}')  `,
    backgroundPosition: props.bgpos || "center",
    backgroundSize: "cover",
    backgroundRepeat: `${width}px ${height}px`,
    width: "100%"
  };

  return (
    <div style={backgd} ref={ref}>
      <div className={classes.overlay}>
        {props.topOpacity && <div className={classes.topOpacity} />}
        <div className={classes.padding}>
          ... CONTENT
        </div>
        {props.bottomOpacity && <div className={classes.bottomOpacity} />}
      </div>
    </div>
  );
}

Upvotes: 0

Views: 1009

Answers (1)

Temani Afif
Temani Afif

Reputation: 273067

this can be done using mask.

Here is a simplified example:

.box {
  height:60vh;
  font-size:50px;
  text-align:center;
  color:#fff;
  position:relative;
  z-index:0;
}
.box:before {
  content:"";
  position:absolute;
  z-index:-1;
  left:0;
  right:0;
  top:-50px;
  bottom:-50px;
  background:var(--img) center/cover;
  -webkit-mask:linear-gradient(transparent ,#fff 50px calc(100% - 50px),transparent);
          mask:linear-gradient(transparent ,#fff 50px calc(100% - 50px),transparent);
}
<div class="box" style="--img:url(https://picsum.photos/id/1002/800/800.jpg)">text 1</div>
<div class="box" style="--img:url(https://picsum.photos/id/109/800/800.jpg)">text 2</div>
<div class="box" style="--img:url(https://picsum.photos/id/107/800/800.jpg)">text 3</div>
<div class="box" style="--img:url(https://picsum.photos/id/177/800/800.jpg)">text 4</div>

Upvotes: 1

Related Questions