1

I am working on a web app, and I am trying to make it responsive, but I am running into a few problems. I am using media queries to detect if the screen width is > than a certain amount or < than a certain amount. Based on that, I would want to change the layout of my component, so that it does not cram and move everything out of alignment. However, it seems like if my goal is to reorder the child components within my component using conditional rendering based on the media query result, then my code would be repeated multiple times. Hence, I am checking to see if there are any other ways to accomplish this.

Below is a screenshot of the browser when the screen size gets smaller, the contents get too cramped up, and hence it messes up the alignment.

Below is a snippet of my code (this code represents the right side of the image -> Revenue and Revenue KPI)

<Row justify="space-around">
    <Col span={11}>
        <Statistic
            title="Revenue"
            value={data[metric].revenue}
            valueStyle={{ color: '#3f8600' }}
        />
    </Col>
    <Divider type="vertical" />
    <Col span={11}>
        Revenue KPI
        <Button shape='circle' size='small' onClick={() => handleClick('rev', metric, 'post')} style={{ marginLeft: '5%' }}>
            <PlusOutlined />
        </Button>
        <Statistic
                value={data[metric].rev_kpi}
                valueStyle={{ color: '#3f8600' }}
        />
    </Col>
</Row>

What I would want to do, is to change the grid layout once the screen width is smaller than a certain amount, and instead of the components above being in the same Row, I would want each to be in their Row (stacking on top of each other). However, if I were to do this using conditional rendering, it seems like I would have to repeat the code quite a fair bit, which seems tedious and messy. Hence, I am hoping if there are any more efficient methods to achieve what I would want to make.

The UI package I am using is AntD (where I got the components for Row, Col, Statistic, Button) https://ant.design/components/grid/

this is my media query function (I use this function to return a boolean based on the query I pass in)

import { useEffect, useState } from "react";

function useMediaQuery(
    query,
    defaultMatches = window.matchMedia(query).matches
) {
    const [matches, setMatches] = useState(defaultMatches);

    useEffect(() => {
        const media = window.matchMedia(query);

        if (media.matches !== matches) setMatches(media.matches);

        const listener = () => setMatches(media.matches);

        media.addListener(listener);

        return () => media.removeListener(listener);
    }, [query, matches]);

    return matches;
}

export default useMediaQuery;

All help is appreciated, thanks all! Do guide me along as I am new to React and especially new to implementing responsive websites!

2
  • 1
    Just a tip: your useEffect might get you in trouble, it is triggered by changing "matches" and it also changes "matches" itself. That might end up creating an infinite rendering loop and a serious headache to debug :) Commented Jun 25, 2020 at 15:09
  • oh, okay i will look into it, thanks! never noticed that loophole haha thank you Commented Jun 25, 2020 at 17:04

1 Answer 1

1

Since Row and Col in ant design seems to be based on flex you should try to use the CSS order property to re-arrange your elements

https://developer.mozilla.org/en-US/docs/Web/CSS/order

It is also available as a prop on the Col component:

https://ant.design/components/grid/#Col

CSS order demo (use media query to change order value for various screen sizes):

div {
  display: flex;
  flex-direction: column;
}


#reverse:checked ~ div>p:first-child {
  order: 2;
}
<input type="checkbox" id="reverse"/>
<label for="reverse">reverse</label>
<div>
  <p>First text element in HTML</p>
  <p>Second text element in HTML</p>
<div>

For even more complex rearrangement of your elements you could use CSS Grid:

  • grid-template-areas: give custom names to areas in your grid
  • grid-area: place element in the grid using one of your custom names

use media-queries to change grid-template-areas and it should work nicely

https://css-tricks.com/snippets/css/complete-guide-grid/

Sign up to request clarification or add additional context in comments.

2 Comments

thank you for answering :-) i tried passing the order as props for the Col, but it seems like the order does not work for Row. Would it be better for me to try to manipulate the imported antd component of Row by trying to overwrite the css used for it, or would it be better for me to convert all of my grid layouts to standard css for easier manipulation? thanks once again for your answer!
I think you don't need to rewrite everything, give your rows a className and use it to change the css order property

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.