Stuart Brown
Stuart Brown

Reputation: 987

React Bootstrap Cards and CardDeck Components - responsive layout

I'm using React Bootstrap and am pulling data from an API using Axios. I'm trying to display the data from that API in bootstrap Card / CarDeck components. I have most of it working using the code below but I'm having problems with the layout.

I'd like to be able to have the card deck be responsive and show a flexible number of cards per row depending on the screen size. At the moment if there are lots of items in the response each card is ridiculously thin and can't be viewed. What is the correct way to do this?

import React, { useState, useEffect } from "react";
import CardDeck from "react-bootstrap/CardDeck";
import Card from "react-bootstrap/Card";
import axios from "axios";
import Container from "react-bootstrap/Container";

const CardColumns = () => {
  const [cardInfo, setData] = useState([]);
  console.log(cardInfo);

  useEffect(() => {
    axios
      .get(
        "https://webhooks.mongodb-realm.com/api/client/v2.0/app/cards-fvyrn/service/Cards/incoming_webhook/getAllCards"
      )
      .then((response) => {
        setData(response.data);
        console.log(response.data);
      })
      .catch(function (error) {
        console.log(error);
      });
  }, []);

  const renderCard = (card, index) => {
    return (
      <Card style={{ width: "18rem" }} key={index} className="box">
        <Card.Img variant="top" src="holder.js/100px180" src={card.image} />
        <Card.Body>
          <Card.Title>
            {index} - {card.manufacturer}
          </Card.Title>
          <Card.Text>{card.player}</Card.Text>
        </Card.Body>
      </Card>
    );
  };

  return <CardDeck>{cardInfo.map(renderCard)}</CardDeck>;
};
export default CardColumns;

Upvotes: 3

Views: 8704

Answers (3)

Dalton Whyte
Dalton Whyte

Reputation: 717

Here are my suggestions for this issue:

  1. Each card should have a min-width to ensure that they do not shrink below a certain amount. So instead of width: "18rem" try min-width: "18rem". If your CSS is properly set up it should cause other cards to overflow to the next row.
  2. You can make use of media-queries or grid layout as mentioned to determine how many cards you want to show for various screen types based on their varying widths say see this link media-query-breakpoints react-bootstrap-grid
  3. Also you can try using CSS flexbox layout, I have an article on this CSS Flex Box

Upvotes: 2

Stuart Brown
Stuart Brown

Reputation: 987

In the end this is the solution I went with the below. Key I think were:

  1. Wrapping the cardDeck in <Container> and then wrapping the cards with <Col className="container-fluid mt-4">:

`

const renderCard = (card, index) => {
return (`
  <Col className="container-fluid mt-4">
    {/* <Card key={index} className="box"> */}
    <Card style={{ width: "18rem" }} key={index} className="box">
      <Card.Header>
        {card.brand} - {card.series}
      </Card.Header>
      <Card.Img variant="top" src={card.front_image} fluid />
      <Card.Body>
        <Card.Title>
          {card.player} (#
          {card.card_number.$numberDouble}) {card.variation}
        </Card.Title>
        {/* <Card.Text className="d-flex">{card.player}</Card.Text> */}
        {/* <Card.Text>{card.player}</Card.Text> */}
      </Card.Body>
      <ListGroup className="list-group-flush">
        <ListGroupItem>
          Print Run - {card.print_run.$numberDouble}
        </ListGroupItem>
        <ListGroupItem>Career Stage - {card.career_stage} </ListGroupItem>
        <ListGroupItem>For Trade - {card.forTrade}</ListGroupItem>
      </ListGroup>
      <Card.Footer className="text-muted">{card.team}</Card.Footer>
    </Card>
  </Col>

  //{/* </Col> */}
);
  };

  return (
<Container>
  <Button variant="primary">Filter By Brand</Button>{" "}
  <Button variant="primary">Filter By Player</Button>{" "}
  <Button variant="primary">Filter By Team</Button>
  <CardDeck>{cardInfo.map(renderCard)}</CardDeck>
</Container>
);`

Upvotes: 4

Iago Calazans
Iago Calazans

Reputation: 328

Try to use a col-'n' to each card instead of a fix width.

...
import { Card, Col } from 'react-bootstrap';
...
    <Col md="n"> // n must be your desired width like
        <Card key={index} className="box">
            ...
    </Col>

You can see more at: Bootstrap Card Sizing

Upvotes: 0

Related Questions