2

On my blog page I'm currently listing all my blog posts in a list with one blog post per row. I'm now trying to change the layout of the page and displaying two and three blog posts per row every other time. Like this:

   [POST] [POST]

[POST] [POST] [POST]

  [POST] [POST]

[POST] [POST] [POST]

etc....

With my current setup I have a Post component which is the HTML Framework and then a DataFunction component which receives the data from the API and returns a list of Post components which then is display on the page.

import React from 'react';
import './style.css'
import PropTypes from 'prop-types'
import Butter from 'buttercms'
import {
    Link
} from 'react-router-dom';

const butter = Butter('XXXXXX');

class Post extends React.Component {
    render() {
        return (
            <div className="App-post grey-background" onClick={this.props.blogPostClick}>
                <div className="butter-page-container">
                    <div className="blog-item-small-img">
                        <img src={this.props.hero_image} alt="Blog images" />
                    </div>
                    <div className="small-text-module blog-item-text">
                        <Link to={`/post/${this.props.slug}` }>
                            <h4 className="text-green ng-btm">{this.props.headline}</h4>
                            <p className="text-green">{this.props.read_time} | {this.props.industry}</p>
                            <p className="text-green">{this.props.description}</p>
                        </Link>
                    </div>
                </div>
            </div>
        );
    }
}

class dataFunction extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            loaded: false
        };
    }

    componentWillMount() {
        butter.page.list('blog-posts').then((resp) => {
            this.setState({
                loaded: true,
                post: resp.data.data
            })
        });
    }
    render() {
        if (this.state.loaded) {
            const posts = this.state.post;
            return (
                posts.map((item, index) => <Post key={index} slug={item.slug} headline={item.fields.headline} read_time={item.fields.read_time} description={item.fields.description} industry={item.fields.industry} hero_image={item.fields.hero_image} />)
            );
        } else {
            return (
                <div>
                    Loading...
                </div>
            );
        }
    }
}

Post.propTypes = {
    blogPostClick: PropTypes.func,
    hero_image: PropTypes.string,
    headline: PropTypes.string,
    industry: PropTypes.string,
    readtime: PropTypes.string,
    description: PropTypes.string
}

export default dataFunction;

Besides above code I have a page which imports the dataFunction and render it.

Any suggestions?

lvj
  • 138
  • 9

1 Answers1

1

There are some way to do it. It's a bit harder to do it only with css (although if I have a working idea, I'll update the answer).

Using code, the logic is to basically "break" the line after each 3rd and 5th items.

Here is a "pseudo" code that does this:

const items = data.map((_, i) => {
  const idx = i + 1;
  const shouldBreak = !(idx % 5) || !((idx % 5) % 3);
  return (
    <React.Fragment>
      <div className="col">{i + 1}</div>
      {shouldBreak && <div className="breaker" />}
    </React.Fragment>
  );
});
.grid {
  text-align: center;
}
.col {
  display: inline-block;
  margin: 5px;
  width: calc(33% - 10px);
  background: pink;
}

https://codesandbox.io/s/angry-wilbur-kgps0


Thanks to @MichaelBenjamin with his great answer there is a css based solution using grid

.grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  grid-auto-rows: 40px;
  grid-gap: 10px;
}

.col:nth-child(5n + 1),
.col:nth-child(5n + 2),
.col:nth-child(5n + 3) {
  grid-column: span 4;
}
.col:nth-child(5n + 4) {
  grid-column: 3 / span 4;
}
.col:nth-child(5n + 5) {
  grid-column: 7 / span 4;
}

.col {
  background-color: tomato;
}

https://codesandbox.io/s/upbeat-dhawan-izjpf

Mosh Feu
  • 28,354
  • 16
  • 88
  • 135