How to stop Flickering a moving image in Nextjs - react-redux

I'm new to next and I have been trying to make the game flappy bird. I used useEffect and styled components to animate the player(or bird) and pipes too. Basically when I run my app on chrome, it works fine but it flickers in safari. And after I play it a few times in safari it starts to work almost fine. For state management, I'm using redux.
Can someone help me to solve the problem and explain what is actually going on?
From what I think it is because of the re-rendering of the images but why is it working properly in chrome? And is there a better way to animate this?
This is my main code and I used the useEffect inside Bird and Pipes file to move them across the GameBox
import styled from 'styled-components'
import Pipes from './Pipes'
import { startGame, setBirdPosition, resetGame } from './features/app-slice'
import { store, constants } from './store'
import { useSelector } from 'react-redux'
import Bird from './Bird'
import { useEffect, useState } from 'react'
export default function GameBox() {
const [jumpAudio, setAudio] = useState(null)
useEffect(() => {
setAudio(new Audio('/sound-effects/jump.wav'))
// only run once on the first render on the client
}, [])
const birdPosition = useSelector((state) => state.birdPosition)
const score = useSelector((state) => state.score)
const gameStarted = useSelector(state => state.gameStarted)
const isGameOver = useSelector(state => state.isGameOver)
function jump() {
const JUMP = constants.JUMP
if (isGameOver) {
store.dispatch(resetGame())
return
}
else if (!gameStarted) {
// store.dispatch(resetGame())
store.dispatch(startGame())
}
else if (birdPosition - JUMP >= 0)
store.dispatch(setBirdPosition(-JUMP))
else store.dispatch(setBirdPosition(0))
jumpAudio.pause();
jumpAudio.currentTime = 0;
jumpAudio.play()
}
return (
<Box onClick={jump}>
{isGameOver ? <GameOver /> : null}
{gameStarted || isGameOver ? <Score>{score}</Score> : null}
{true ? <Bird /> : null}
<Pipes height={200} />
{!gameStarted && !isGameOver ? <GameStart /> : null}
{/* <Pipes height={200} position={props.width + 300} wh={props.height} /> */}
</Box>
)
}
const Box = styled.div`
user-select: none; /* supported by Chrome and Opera */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Firefox */
-ms-user-select: none;
background: no-repeat center/100% url('/img/background-day.png');
overflow: hidden;
position: relative;
width: ${constants.WINDOW_WIDTH}px;
height: ${constants.WINDOW_HEIGHT}px
`
const GameStart = styled.div`
background: no-repeat center/70% url('/img/gamestart.png');
text-align: center;
width: 100%;
height: 100%;
`
const GameOver = styled.div`
position: relative;
z-index: 10;
background: no-repeat center/70% url('/img/gameover.png');
text-align: center;
width: 100%;
height: 100%;
`
const Score = styled.div`
font-family: 'Gamja Flower', cursive;
color: white;
text-shadow: black 2px 2px;
position: absolute;
font-size: 3rem;
z-index:1;
right: 10%;
top: 0;
`

Related

How to fade one react component out, then fade another in?

I've got 2 components that are conditionally shown or hidden based on a string value stored in useState as showModal
{showModal === 'SIGNIN' && <SignIn />}
{showModal === 'JOIN' && <Join />}
I want to fade in one component, then when the state changes, fade it out and fade in the other component.
Can this be done with react transition group?
I tried
<TransitionGroup>
<CSSTransition in={showModal === 'SIGNIN' ? true : false} classNames='fade' timeout={220} key={showModal}>
<div>
<SignIn />
</div>
</CSSTransition>
<CSSTransition in={showModal === 'JOIN' ? true : false} classNames='fade' timeout={220} key={showModal}>
<div>
<Join />
</div>
</CSSTransition>
</TransitionGroup>
I don't get any error, one component is shown, changing showModal from 'SIGNIN' to 'JOIN' does nothing. Inspecting the divs with the timeout set to 22000 shows that no new classes have been added.
SwitchTransition from react transition group might help.
Example
const { useState, useEffect } = React;
const { SwitchTransition, CSSTransition } = ReactTransitionGroup;
const SignIn = () => <div className="block sign-in">Sign In</div>;
const Join = () => <div className="block join">Join</div>;
const App = () => {
const [showModal, setModal] = useState("SIGNIN");
useEffect(() => {
let handle;
const loop = () => {
setModal(state => state === "JOIN" ? "SIGNIN" : "JOIN");
handle = setTimeout(loop, 2500);
};
handle = setTimeout(loop, 1000);
return () => {
clearTimeout(handle);
}
}, []);
const addEndListener = (node, done) => {
node.addEventListener("transitionend", done, false);
}
return <div>
<SwitchTransition mode="out-in">
<CSSTransition
key={showModal === "SIGNIN"}
addEndListener={addEndListener}
classNames="fade">
{showModal === "SIGNIN" ? <SignIn/> : <Join/>}
</CSSTransition>
</SwitchTransition>
</div>;
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
body {
margin: 0;
overflow: hidden;
font-family: Georgia, serif;
}
.block {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 10px;
color: white;
width: 200px;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
font-size: 30px;
}
.sign-in {
background: #0984e3;
}
.join {
background: #6c5ce7;
}
.fade-enter {
opacity: 0;
transform: translate(-100%, -50%);
}
.fade-exit {
opacity: 1;
transform: translate(-50%, -50%);
}
.fade-enter-active {
opacity: 1;
transform: translate(-50%, -50%);
}
.fade-exit-active {
opacity: 0;
transform: translate(100%, -50%);
}
.fade-enter-active,
.fade-exit-active {
transition: opacity 500ms, transform 500ms;
}
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/react-transition-group#4.4.2
/dist/react-transition-group.min.js"></script>
<script src="https://unpkg.com/babel-standalone#6/babel.min.js"></script>
<div id="root"></div>

Gatsby / GraphQL App - Rendering and Style Issues When Deployed (Netlify and Surge)

Built a portfolio page with Gatsby / GraphQL, using styled components. On my local machine, it looks and functions exactly as I want it to. When deployed, there seem to be button style issues and one of my images isn't rendering at all. I tried deploying on both Netlify and Surge.sh, but had the same result both times. What am I doing incorrectly? Edit: could my button styles be affected by how Link is used?
Here are how my button styles look locally:
Here's how they look deployed ('View Repo' doesn't even work deployed):
My 'About Me' section locally (2 columns):
My 'About Me' section deployed (only column 1 shows):
gatsby-config.js
module.exports = {
siteMetadata: {
title: `Portfolio`,
description: `Lorem ipsum.`,
author: `#jordanwhunter`,
},
plugins: [
`gatsby-plugin-react-helmet`,
`gatsby-plugin-image`,
`gatsby-plugin-styled-components`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/assets/images`,
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
name: `videos`,
path: `${__dirname}/src/assets/videos`,
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `gatsby-starter-default`,
short_name: `starter`,
start_url: `/`,
background_color: `#663399`,
theme_color: `#663399`,
display: `minimal-ui`,
icon: `src/assets/images/memoji.jpeg`, // This path is relative to the root of the site.
},
},
`gatsby-plugin-gatsby-cloud`,
`gatsby-transformer-json`,
{
resolve: `gatsby-source-filesystem`,
options: {
path: `./src/data/`,
},
},
],
}
package.json
{
"name": "gatsby-starter-default",
"private": true,
"description": "A simple starter to get up and developing quickly with Gatsby",
"version": "0.1.0",
"author": "Kyle Mathews <mathews.kyle#gmail.com>",
"dependencies": {
"babel-plugin-styled-components": "^1.12.0",
"gatsby": "^3.0.1",
"gatsby-image": "^3.0.0",
"gatsby-plugin-gatsby-cloud": "^2.0.0",
"gatsby-plugin-image": "^1.0.0",
"gatsby-plugin-manifest": "^3.0.0",
"gatsby-plugin-offline": "^4.0.0",
"gatsby-plugin-react-helmet": "^4.0.0",
"gatsby-plugin-sharp": "^3.0.0",
"gatsby-plugin-styled-components": "^4.0.0",
"gatsby-source-filesystem": "^3.0.0",
"gatsby-transformer-json": "^3.0.0",
"gatsby-transformer-sharp": "^3.0.0",
"gh-pages": "^3.1.0",
"prop-types": "^15.7.2",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-helmet": "^6.1.0",
"react-icons": "^4.2.0",
"styled-components": "^5.2.1",
"surge": "^0.22.1"
},
"devDependencies": {
"prettier": "2.2.1"
},
"keywords": [
"gatsby"
],
"license": "0BSD",
"scripts": {
"build": "gatsby build",
"develop": "gatsby develop",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md}\"",
"start": "npm run develop",
"serve": "gatsby serve",
"clean": "gatsby clean",
"test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://github.com/gatsbyjs/gatsby-starter-default"
},
"bugs": {
"url": "https://github.com/gatsbyjs/gatsby/issues"
}
}
Portfolio.js (button code starts on line 226)
import React from 'react'
import { useStaticQuery, graphql } from "gatsby"
import { Button } from "./Button"
import Img from "gatsby-image"
import styled from "styled-components"
const PortfolioContainer = styled.div`
min-height: 100vh;
padding: 5rem calc((100vw - 1300px) / 2);
background: #fff;
color: #fff;
`
const PortfolioHeading = styled.div`
font-size: clamp(1.5rem, 5vw, 2.5rem);
text-align: center;
margin-bottom: 5rem;
color: #000;
`
const PortfolioImg = styled(Img)`
height: 100%;
max-width: 100%;
position: absolute;
border-radius: 10px;
filter: brightness(100%);
transition: 0.4s cubic-bezier(0.075, 0.82, 0.165, 1);
`
const PortfolioWrapper = styled.div`
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 10px;
justify-items: center;
padding: 0 2rem;
#media screen and (max-width: 1200px) {
grid-template-columns: 1fr 1fr;
}
#media screen and (max-width: 868px) {
grid-template-columns: 1fr;
}
`
const PortfolioInfo = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
align-content: center;
align-items: center;
justify-items: center;
padding: 0 2rem;
visibility: hidden;
opacity: 0;
transition: opacity .2s, visibility .2s;
#media screen and (max-width: 280px) {
padding: 0 1rem;
justify-content: center;
align-content: center;
}
`
const PortfolioCard = styled.div`
line-height: 2;
width: 100%;
height: 500px;
position: relative;
border-radius: 10px;
transition: 0.2s ease;
&:hover ${PortfolioInfo}{
visibility: visible;
opacity: 1;
}
&:hover ${PortfolioImg}{
filter: brightness(50%)
}
`
const TextWrap = styled.div`
display: flex;
align-items: center;
text-align: center;
position: absolute;
top: 375px;
flex-wrap: wrap;
justify-content: center;
align-content: center;
width: 87%;
`
const PortfolioTitle = styled.div`
font-weight: 400;
font-size: 1rem;
margin-left: 0.5rem;
#media screen and (max-width: 280px) {
font-size: 12px;
}
`
const PortfolioDescription = styled.div`
font-size: 1rem;
#media screen and (max-width: 280px) {
font-size: 12px;
}
`
const PortfolioTechnologies = styled.div`
font-size: 1rem;
#media screen and (max-width: 280px) {
font-size: 12px;
}
`
const ButtonLink = styled.a`
text-decoration: none;
cursor: pointer;
`
const ButtonWrap = styled.div`
display: flex;
flex-direction: row;
position: absolute;
justify-content: center;
align-content: center;
align-items: center;
width: 100%;
height: -400px;
z-index: 1;
gap: 10px;
#media screen and (max-width: 280px) {
padding: 0 1rem;
justify-content: center;
align-content: center;
}
`
const CustomButton = styled(Button)`
display: flex;
align-items: center;
position: relative;
font-size: 14px;
width: 100%;
cursor: pointer;
top: -60px;
#media screen and (max-width: 480px) {
background: none;
border: none;
padding: 0 !important;
font-family: arial, sans-serif;
color: #fff;
text-decoration: underline;
cursor: pointer;
width: 100%;
font-size: 12px;
justify-content: center;
}
`
const CustomP = styled.p`
font-size: 12px;
`
export default function Portfolio({ heading }) {
const data = useStaticQuery(graphql`
query PortfolioQuery {
allPortfolioJson {
edges {
node {
alt
button1
button2
description
name
technologies
demo
repo
img {
childImageSharp {
fluid {
...GatsbyImageSharpFluid
}
}
}
}
}
}
}
`)
function getPortfolio(data) {
const portfolioArray = []
data.allPortfolioJson.edges.forEach((item, index) => {
portfolioArray.push(
<PortfolioCard key={index}>
<PortfolioImg
src={item.node.img.childImageSharp.fluid.src}
fluid={item.node.img.childImageSharp.fluid}
alt={item.node.alt}
/>
<PortfolioInfo>
<TextWrap>
<PortfolioTitle
css={`
margin-top: -500px;
`}
>
<strong><u>Project:</u></strong> <br />
{item.node.name}
</PortfolioTitle>
<PortfolioDescription
css={`
margin-top: -300px;
`}
>
<strong><u>Description:</u></strong> <br />
{item.node.description}
</PortfolioDescription>
<PortfolioTechnologies
css={`
margin-top: -100px;
`}
>
<strong><u>Technologies:</u></strong> <br />
{item.node.technologies}
</PortfolioTechnologies>
</TextWrap>
<ButtonWrap>
<ButtonLink
href={`${item.node.demo}`}
target="_blank"
>
<CustomButton
primary="true"
round="true"
>
{item.node.button1}
</CustomButton>
</ButtonLink>
<ButtonLink
href={`${item.node.repo}`}
target="_blank"
>
<CustomButton
primary="true"
round="true"
>
{item.node.button2}
</CustomButton>
</ButtonLink>
</ButtonWrap>
</PortfolioInfo>
</PortfolioCard>
)
})
return portfolioArray;
}
return (
<PortfolioContainer id="portfolio">
<PortfolioHeading>
{heading}
<CustomP>(Tap on Mobile)</CustomP>
</PortfolioHeading>
<PortfolioWrapper>
{getPortfolio(data)}
</PortfolioWrapper>
</PortfolioContainer>
)
};
About.js (column 2 code starts on line 137):
import React from 'react'
import { useStaticQuery, graphql } from 'gatsby';
import { GrCircleInformation, GrCode, GrDocumentImage } from "react-icons/gr";
import styled from "styled-components"
import Img from "gatsby-image"
const AboutContainer = styled.div`
width: 100%;
background: #fcfcfc;
color: #000;
padding: 5rem calc((100vw - 1300px) / 2);
height: 100%;
border-top: 1px solid gray;
border-bottom: 1px solid gray;
`
const TopLine = styled.div`
color: #077bf1;
font-size: 1rem;
padding-left: 2rem;
margin-bottom: 0.75rem;
`
const Description = styled.p`
text-align: start;
padding-left: 2rem;
margin-bottom: 4rem;
font-size: clamp(1.5rem, 5vw, 2rem);
font-weight: bold;
`
const ContentWrapper = styled.div`
display: grid;
grid-template-columns: 1fr 1fr;
padding: 0 2rem;
#media screen and (max-width: 768px) {
grid-template-columns: 1fr;
}
`
const ColumnOne = styled.div`
display: grid;
grid-template-rows: 1fr 1fr;
`
const Biography = styled.div`
padding-top: 1rem;
padding-right: 2rem;
h3 {
margin-bottom: 1rem;
font-size: 1.5rem;
font-style: italic;
}
p {
color: #3b3b3b;
}
`
const ColumnTwo = styled.div`
display: grid;
grid-template-columns: 1fr;
margin-top: 2rem;
grid-gap: 10px;
#media screen and (max-width: 500px) {
grid-template-columns: 1fr;
}
`
const Image = styled(Img)`
border-radius: 10px;
height: 100%;
margin-top: -50px;
#media screen and (max-width: 375px) {
margin-top: 0;
}
`
export default function About() {
const data = useStaticQuery(graphql`
query MyQuery {
allFile(filter: {ext: {regex: "/(jpg)|(png)|(jpeg)/"}, name: {in: ["profile-photo"]}}) {
edges {
node {
childImageSharp {
fluid {
...GatsbyImageSharpFluid
}
}
}
}
}
}
`)
return (
<AboutContainer id="about">
<TopLine>
About Me
</TopLine>
<Description>
<div css={`display: flex;`}>
<GrDocumentImage /><h4 css={`font-style: italic;`}>Resumes</h4>
</div>
<div
css={`
display: flex;
font-size: 14px;
margin-bottom: -40px;
`}
>
<p>
Resume 2021 (ATS Version)<br />
Resume 2021 (Styled Version)
</p>
</div>
</Description>
<ContentWrapper>
<ColumnOne>
<Biography>
<div css={`display: flex;`}>
<GrCircleInformation /><h3>Brand Statement</h3>
</div>
<p>
Full stack web/software developer with an entrepreneurial spirit, and keen sense of efficiency and time management. A passionate, goal-oriented team player that strives to always write clean, precise code focused on mobile responsive themes. Maintains a problem solving, can-do attitude and exhibits consistent eagerness to learn new technologies/techniques.
</p>
</Biography>
<Biography>
<div css={`display: flex;`}>
<GrCode />
<h3>Technologies</h3>
</div>
<p>
JavaScript, React, Preact, Next, Gatsby, Svelte, Node, Express, Firebase, Vercel, MongoDB, MySQL, Handlebars, jQuery, D3, GraphQL, Material-UI, CSS3, Bootstrap, Materialize, Bulma, HTML5
</p>
</Biography>
</ColumnOne>
<ColumnTwo>
{data.allFile.edges.map((image, key) => (
<Image
key={key}
src={image.node.childImageSharp.src}
fluid={image.node.childImageSharp.fluid}
/>
))}
</ColumnTwo>
</ContentWrapper>
</AboutContainer>
)
};
Inspect generated html:
<div class="Portfolio__ButtonWrap-zwd7jb-14 boxtca">
<a href="https://filmapi.vercel.app/" target="_blank" class="Portfolio__ButtonLink-zwd7jb-13 dHdqal">
<a primary="true" round="true" class="Button-sc-1t76fnu-0 Portfolio__CustomButton-zwd7jb-15 iA-DhcJ cycuPQ">View App</a>
</a>
<a primary="true" round="true" class="Button-sc-1t76fnu-0 Portfolio__CustomButton-zwd7jb-15 iA-DhcJ cycuPQ">
<a primary="true" round="true" class="Button-sc-1t76fnu-0 Portfolio__CustomButton-zwd7jb-15 iA-DhcJ cycuPQ">View Repo</a>
</a>
</div>
Observation #1:
bad structure for a second button (not a ButtonLink);
Why:
messed virtual DOM [and as a result real DOM];
Possible reason:
multiple, the same kind children rendered without key prop (the most frequent bad React rendering reason?);
Solution #1: always use a key prop for [elements of] lists/arrays/groups!
'About me' missing column problem:
Observation #2:
before (at first render) and during [image] loading html/DOM structure is OK;
React update (rerendering) breaks child divs [of AboutContainer] - no keys used (then no unique identifiers for multiple divs in VDOM), result - the update breaks the content structure.
But this is not the only reason - the real one was using <Img/>-based component - outdated for new gatsby image plugins [versions].
Solution #2:
You should use <GatsbyImage/> components.
Always make sure the documentation you're referencing is current!
There are significant syntax changes with graphql and using the GatsbyImage / StaticImage components from gatsby-plugin-image instead of the Img component from gatsby-image.
To fix Portfolio.js - the image rendering was affecting the button links - code had to be refactored for the current syntax referencing the GatsbyImage component from gatsby-plugin-image. graphql and useStaticQuery syntax also had to be refactored. For more information, visit Gatsby's documentation (thanks to #xadm for pointing me in the right direction).
About.js was also fixed by updating syntax...except this Img tag was changed to StaticImage and graphql and useStaticQuery were removed entirely.

How to style dropdown with styled-components

I am using React JS + Typescript for my app. For styling I am using styled-components. I am really new in styled components. I have created one dropdown. The logic works fine but the UI looks horrible. I uploaded my code in Code sand box. I want design my Dropdown like Tailwind. But since I am new styled-components, I just don't know how to do that.
This is my dropdown component
import React, { useState } from "react";
import styled from "styled-components";
import Arrow from './Arrow.svg'
const Wrapper = styled.div<
{
active: boolean;
}
>`
text-align: left;
width: 100%;
color: #bfc5cd;
font-size: 16px;
font-weight: 300;
position: relative;
margin: 2em 0;
#media (min-width: 400px) {
max-width: 300px;
}
svg {
fill: #798697;
transition: all 0.2s ease;
}
${props =>
props.active
? `
svg {
transform: rotate(180deg);
}
`
: ``}
`;
const MenuLabel = styled.span`
display:inline-block;
color: grey;
border: 1px solid green;
background: white;
box-shadow: 0 0 5px -1px rgba(0,0,0,0.2);
cursor:pointer;
vertical-align:middle;
max-width: 100px;
padding: 40px 40px;
font-size: 12px;
text-align: center;
border: 1px solid ${({ theme }) => theme.inputBorderColor};
&:focus {
outline: none;
box-shadow: 0px 0px 0px 1px ${({ theme }) => theme.inputBorderColorActive};
border: 1px solid ${({ theme }) => theme.inputBorderColorActive};
}
`;
const ItemList = styled.div`
color: #798697;
background: white;
line-height: 30px;
padding: .25em 2em .25em 2em;
cursor: defaul;
user-select: none;
transition: all .25s ease;
&:hover,
&.selected {
background: #F7F7F7;
color: #4A4A4A;
}
`;
export interface IOptions {
label: string;
value: number;
}
export interface IDropdown {
labelDefault: string;
options: IOptions[];
}
const Dropdown = ({ labelDefault, options }: IDropdown) => {
const [isOpened, setIsOpened] = useState(false);
const [selectedOption, setSelectedOption] = useState("");
const [label, setLabel] = useState("");
const handleSelectedItem = (obj: any) => {
setSelectedOption(obj.value);
setLabel(obj.label);
setIsOpened(!isOpened);
};
return (
<Wrapper active={isOpened}>
<MenuLabel onClick={() => setIsOpened(!isOpened)}>
{selectedOption ? label : labelDefault}
</MenuLabel>
<ul
style={
isOpened
? {
display: "block",
listStyleType: "none"
}
: { display: "none" }
}
>
{options.map(el => (
<ItemList
key={el.value.toString()}
onClick={() => handleSelectedItem(el)}
>
{el.label}
</ItemList>
))}
</ul>
</Wrapper>
);
}
export default Dropdown;
This is the parent component
import * as React from "react";
import Dropdown from "./dropdown";
const MockData = [
{ label: "one", value: 1 },
{ label: "two", value: 2 },
{ label: "three", value: 3 }
];
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<Dropdown labelDefault="Select a label" options={MockData} />
</div>
);
}

How can I use a unique image as modal content with HTML/CSS/JS?

I would like it if you clicked on one image, another image would pop up as a modal. I would like the modal content to be a separate image from the trigger, but I borrowed this code from W3Schools and it is written for the same image.
I have tried putting a different image file as src in line 4 with modal-content (id=img01). I have tried changing the var img in line 8 to "img01". I have played around with those two lines in different combinations, but no luck.
I tried to make this as concise as possible, but not entirely sure which parts are the issue, so please forgive any extraneous code, and I can give more if you suspect there is something I'm not including.
Any help is greatly appreciated!!! :)
HTML
<img id="myImg" src="graphic.jpeg" alt="">
<div id="myModal" class="modal"> <span class="close">×</span>
<img class="modal-content" id="img01"> </div>
JS
var modal = document.getElementById('myModal');
var img = document.getElementById('myImg');
var modalImg = document.getElementById("img01");
img.onclick = function(){
modal.style.display = "block";
modalImg.src = this.src;
}
var span = document.getElementsByClassName("close")\[0\];
span.onclick = function() {
modal.style.display = "none";
}
CSS
img {
padding: 0;
display: block;
margin: 0 auto;
max-height: 100%;
max-width: 100%;
}
#img01 {
height: 100%;
width: auto;
}
#myImg {
border-radius: 5px;
cursor: pointer;
transition: 0.3s;
}
.modal {
display: none;
position: fixed;
z-index: 1;
padding-top: 100px;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgb(0,0,0);
background-color: rgba(0,0,0,0.9);
}
.modal-content {
margin: auto;
display: block;
width: 80%;
max-width: 700px;
}
Modal image content is loaded in JS line modalImg.src = this.src.
Try modalImg.src = "sample/url"; instead of that.

Firefox render bug with fixed background images and a filter applied

So I was experimenting with css filter, the experiment worked quite well but not in Firefox.
I wanted to apply a filter onto a segment of the background image. The idea was to fix the background image of the wrapper and the inner elements to create the illusion that the filter is applying only to a certain area and can be moved, here with scrolling.
This is what I tried:
html,
body {
width: 100%;
height: 100%;
}
body {
margin: 0px;
height: 200%;
display: flex;
justify-content: space-around;
align-items: center;
flex-direction: column
}
body,
div {
background-image: url("https://i.imgur.com/wu7EkAX.jpg");
background-attachment: fixed;
}
div {
filter: saturate(0%);
width: 50%;
height: 40%;
}
<div></div>
<div></div>
This works quite well with Chrome (and I think also in other browsers) but not with Firefox. It seems like it is a result of some optimization which misbehaves.
If you scroll with your mousewheele and then click, it refreshes, otherwise it stays in this state (at least if you run it standalone).
The "solution" is quite simple, you force Firefox to re render, there are whole posts about this topic but here are two of my approaches:
With a css animation
#keyframes renderFix {
from {
outline-color: red;
}
to {
outline-color: blue;
}
}
html {
outline: 1px solid red;
animation: 1s infinite alternate renderFix;
}
With some JavaScript
{
let html, s = false,
cycle = function () {
html.style.outlineColor = s ? "red" : "blue"
s = !s;
window.requestAnimationFrame(cycle)
}
window.requestAnimationFrame(function () {
html = document.body.parentElement
html.style.outlineStyle = "solid";
html.style.outlineWidth = "1px";
cycle()
})
}
The JavaScript fix applied:
{
let html, s = false,
cycle = function () {
html.style.outlineColor = s ? "red" : "blue"
s = !s;
window.requestAnimationFrame(cycle)
}
window.requestAnimationFrame(function () {
html = document.body.parentElement
html.style.outlineStyle = "solid";
html.style.outlineWidth = "1px";
cycle()
})
}
html,
body {
width: 100%;
height: 100%;
}
body {
margin: 0px;
height: 200%;
display: flex;
justify-content: space-around;
align-items: center;
flex-direction: column
}
body,
div {
background-image: url("https://i.imgur.com/wu7EkAX.jpg");
background-attachment: fixed;
}
div {
filter: saturate(0%);
width: 50%;
height: 40%;
}
<div></div>
<div></div>

Resources