1

I have a screen which has two divs: top navbar (80px in height) and a div component below the navbar (remaining screen height).

Since I am using tailwind formatting looks something like this:

<div className="w-screen h-[80px]"> //navbar
</div>
<div className="w-screen h-screen"> //bottom content div
</div>

The problem, navbar is 80px and bottom content is dynamic but a white gap appears at the bottom. White gap will disappear if using h-screen (100% vw). enter image description here

Because of the navbar's height of 80px I must dynamic subtract the bottom div (h-screen-80px) otherwise a vertical scroll bar will appear which I dont want. So I have a listener to update the window height depending on the current size of the window (including window resize events). I then subtract this height by 80, compose a string for tailwind and update the className. While it works fine and the inspector shows it is dynamically updating the div's height visually is not adjusting as it should be.

New Attempt with window event listener and calculation. Note the calcualted heightMinusNavbar is correctly updated when resizing the window but visually will not

import React from "react";
import Gallery from "../components/gallery/Gallery";
import Navbar from "../components/navbars/Dapp";

class dashboard extends React.Component {
  constructor(props) {
    super(props);
    this.state = { width: 0, height: 0 };
    this.updateWindowDimensions = this.updateWindowDimensions.bind(this);
  }

  componentDidMount() {
    this.updateWindowDimensions();
    window.addEventListener("resize", this.updateWindowDimensions);
  }

  componentWillUnmount() {
    window.removeEventListener("resize", this.updateWindowDimensions);
  }

  updateWindowDimensions() {
    this.setState({ width: window.innerWidth, height: window.innerHeight });
  }

  // todo: change height to be full screen subtracted by nav height

  render() {
    const heightMinusNavbar = `h-[${(this.state.height - 80).toString()}px]`;
    console.log("heightMinusNavbar " + heightMinusNavbar);

    return (
      <>
        <Navbar />
        <div
          className={`w-screen text-gray-300 y-full bg-gray-900 ${heightMinusNavbar}`}
        >
          <Gallery />
        </div>
      </>
    );
  }
}

export default dashboard;

What am I doing incorrectly?

Potion
  • 785
  • 1
  • 14
  • 36
  • Probably because it is a dynamic class name. https://tailwindcss.com/docs/content-configuration#dynamic-class-names – stickyuser Sep 29 '22 at 14:10
  • Thanks for pointing that out. So what Im doing seems to be an antipattern for Tailwind CSS. Do you suggest I use native javascript without tailwind for this specific case and apply the css to the component instead? Ive done this before in apps in the past but they werent react/tailwind and Im not sure if it is best practice – Potion Sep 29 '22 at 16:54
  • Nevermind I found this solution which says to use react's inline-state styling. The key is to make sure to use a state because react will re-render on state changes. https://stackoverflow.com/questions/50273232/how-to-add-dynamic-css-in-react-js – Potion Sep 29 '22 at 17:15

2 Answers2

1

If your navbar is a fixed height of 80px, you could just use an inline calc class.

<div class="h-20 bg-slate-300">Navbar</div>
<div class="h-[calc(100vh-80px)] bg-slate-100">Gallery</div>

https://play.tailwindcss.com/bOun5kbE3O

stickyuser
  • 2,552
  • 15
  • 15
  • Just tried this and no dice. I dont think this will work. According to this page (https://tailwindcss.com/docs/content-configuration#dynamic-class-names) "Tailwind doesn’t actually evaluate your source code and can only detect static unbroken class strings." – Potion Sep 29 '22 at 17:19
  • It is valid Tailwind CSS, I even linked to a working example. The class is a complete unbroken string. – stickyuser Sep 29 '22 at 17:25
  • I see your example works but for some reason it didnt for my react application. I wonder if I may a setting or something else conflicting with it. – Potion Sep 29 '22 at 18:56
  • In either case yours is a working and acceptable answer. I also provided another solution using react's inline state styling feature. Which of the two solutions would you say is best practice or does it not matter? – Potion Sep 29 '22 at 18:58
  • I would personally go with a single css class, but they are very similar answers. I was even going to suggest using an inline style until I realised it could be done with a Tailwind class. – stickyuser Sep 29 '22 at 20:02
  • 1
    Yes the single css approach is cleaner. For that, I will select yours as the appropriate answer. Thank you for your help! – Potion Sep 29 '22 at 21:11
0

I found a solution:

  • Use Tailwind for static styling (width text-grey-300 y-full bg-gray-900)
  • Use React's Inline-State Styling (height) stored by a variable. Note in the code below I am using style={{ height: this.state.height - 80 }} for the div.

This is because changes in state will re-render the component which is perfect. So the solution then becomes:

import React from "react";
import WalletConnect from "../components/WalletConnect/WalletConnect";
import fren1 from "../assets/fren/1.png";
import pixel1 from "../assets/fren/pix/1.gif";
import fren5 from "../assets/fren/5.png";
import MenuButton from "../components/buttons/MenuButton";
import { NftNamespace } from "alchemy-sdk";
import { collection } from "firebase/firestore";
import Gallery from "../components/gallery/Gallery";
import Navbar from "../components/navbars/Dapp";

class dashboard extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      width: window.innerWidth,
      height: window.innerHeight,
    };
    this.updateWindowDimensions = this.updateWindowDimensions.bind(this);
  }

  componentDidMount() {
    this.updateWindowDimensions();
    window.addEventListener("resize", this.updateWindowDimensions);
  }

  componentWillUnmount() {
    window.removeEventListener("resize", this.updateWindowDimensions);
  }

  updateWindowDimensions() {
    this.setState({
      width: window.innerWidth,
      height: window.innerHeight,
    });
  }

  render() {
    return (
      <>
        <Navbar />
        <div
          className="w-screen text-gray-300 y-full bg-gray-900"
          style={{ height: this.state.height - 80 }}
        >
          <Gallery />
        </div>
      </>
    );
  }
}

export default dashboard;

Potion
  • 785
  • 1
  • 14
  • 36