4

If the open prop value is true I want to apply a position fix to the body element, how can I achieve that using styled components?

export const Navbar = styled.nav`
  box-sizing: border-box;
  overflow-y: scroll;
  justify-content: center;
  background: ${() => "#ffffff"};
  height: 100vh;
  text-align: left;
  padding: 5rem 4rem 2rem;
  top: 0;
  left: 0;
  transition: transform 0.3s ease-in-out;

  transform: ${({ open }) => (open ? "translateX(0)" : "translateX(-110%)")};
 

  body {
    position: ${({ open }) => (open ? "fixed" : "absolute")};
  }
Pep
  • 647
  • 6
  • 20
  • The way this is written, styles will be applied to body tag which is a child of nav, which is not the case. – Sushanth -- Dec 08 '20 at 18:47
  • https://stackoverflow.com/questions/1014861/is-there-a-css-parent-selector – k.s. Dec 08 '20 at 18:48
  • Only in the component, using DOM API – k.s. Dec 08 '20 at 18:49
  • One way I can think of is to pass in props to maintain state in the globalStyles components that uses `createGlobalStyle` API from styled components and update the state based on the prop pass to nav that would update the position of body tag. The other way is to use the DOM API to directly to update the position, but that would be the last resort. – Sushanth -- Dec 08 '20 at 18:50

2 Answers2

1

I'm not familiar with react styled components but I doubt that the syntax with the nested body tag is correct.
You could use a useEffect hook inside your Navbar component though:

useEffect(() => {
  document.body.style.position = open ? 'fixed' : 'absolute';
}, [open]);

This will call the arrow function initially and whenever the open prop changes.

k.s.
  • 2,964
  • 1
  • 25
  • 27
shilch
  • 1,435
  • 10
  • 17
  • 1
    You shouldn't query the document object with React, you have API for that, especially with styled-component where you have `createGlobalStyle` – Dennis Vash Dec 08 '20 at 18:51
1

The right way is to use the library API as querying the document-object/DOM is an anti-pattern in React (that's why you using React in first place).

See body style example:

const GlobalStyle = createGlobalStyle`
body {
  color: ${({ open }) => (open ? "red" : "blue")}
}
`;

export default function App() {
  const [open, toggle] = useReducer((p) => !p, false);
  return (
    <>
      Body Style Example
      <GlobalStyle open={open} />
      <button onClick={toggle}>toggle</button>
    </>
  );
}

Edit Body Style Example

Dennis Vash
  • 50,196
  • 9
  • 100
  • 118