在Gatsby中将网格模板区域与动态内容一起使用

时间:2019-02-14 20:44:16

标签: css reactjs graphql css-grid gatsby

我正在尝试使用CSS网格进行布局,每行上都有交替的列。第一行的图像在左侧,文本在右侧,第二行的文本在左侧,图像在右侧,依此类推。

我尝试使用nth-of-type,但是随着父节点(框)在每个帖子中重复出现,我认为这将非常困难。

问题是我无法单独接触所有孩子,因为内容来自GraphQL,而且我只有一个节点要处理。

有人会建议这样做吗?

谢谢!

import React, { Component } from "react";
import { Link, graphql, StaticQuery } from 'gatsby'
import styled from 'styled-components'
import Img from 'gatsby-image'

const Wrapper = styled.div`
    margin: 0 auto;
    margin-bottom: 6rem;
    overflow: visible;
` 

const Title = styled.h5`
    margin-bottom: 2rem;
    text-align: center;
`

const Inner = styled.div`
    display: grid;
    grid-template-columns: 1fr;
    grid-row-gap: 3rem;

    @media (max-width: 1024px) {
        grid-template-columns: 1fr;
        grid-row-gap: 80px;
        padding: 1rem;
    }
`

const Box = styled.div`
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-column-gap: 6rem;
    align-items: center;

    grid-template-rows: auto;
    grid-template-areas: "left right";

    @media (max-width: 1024px) {
        grid-template-columns: 1fr;
        grid-row-gap: 80px;
        padding: 1rem;
    }
`

const Content = styled.div`
        text-decoration: none;

        &:nth-of-type(even){
            grid-area: right;
        }

        &:nth-of-type(odd){
            grid-area: left;
        }

`

const StyledLink = styled(Link)`
    text-decoration: none;
    color: inherit;

        :nth-of-type(even){
            grid-area: left;
        }

        :nth-of-type(odd){
            grid-area: right;
        }

`

const StyledImg = styled(Img)`
    border-radius: 7px;
    margin-bottom: 1rem;

    opacity: 1;
    -webkit-transition: .5s ease-in-out;
    transition: .5s ease-in-out;

        :hover {
            opacity: .7;
        }
`

const PostTitle = styled.h6`
    margin-bottom: 0.5rem;

`
const Date = styled.p`  
    font-size: 0.8rem;
    display: block;
    color: #777;

`


export class Gallery extends Component {

      render(){
        return (
            <Wrapper>
            <Title>
                Works
            </Title>
                <Inner>
                {this.props.data.allMarkdownRemark.edges.map(({ node }) => (
                    <Box key={node.id} className='box'>
                        <StyledLink to={node.fields.slug}>
                            <StyledImg fluid={node.frontmatter.image.childImageSharp.fluid} />
                        </StyledLink> 
                        <Content>
                            <StyledLink to={node.fields.slug}>
                                <PostTitle>
                                    {node.frontmatter.title}{" "}
                                </PostTitle>
                            </StyledLink>
                            <Date>
                            {node.frontmatter.date}
                            </Date>
                            <p>{node.excerpt}</p>
                        </Content>
                    </Box>
                ))}
                </Inner>
            </Wrapper>
        )
    }
}

export default props => (

    <StaticQuery
    query={graphql`
      query {
          allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) {
              totalCount
              edges {
              node {
                  id
                  frontmatter {
                  title
                  date(formatString: "DD MMMM, YYYY")
                  image {
                  childImageSharp {
                      fluid(maxWidth: 800) {
                      ...GatsbyImageSharpFluid_noBase64
                      }
                  }
              }
                  }
                  fields {
                  slug
                  }
                  excerpt
              }
              }
          }
          }
    `}
    render={data => <Gallery data={data} {...props} />}
    />
)
````


2 个答案:

答案 0 :(得分:0)

使用样式组件,您可以将nth-of-type提升到Box来定位其子对象:

const Inner = styled.div`
  display: grid;
  grid-template-columns: 1fr;
  grid-row-gap: 1rem;
`;

// declare Image & Content first, so we can use it in Box 
const Image = styled.img`
  display: block;
`;

const Content = styled.div`
  display: block;
`;

const Box = styled.div`
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: auto;
  grid-template-areas: "left right";

  & > ${Image}, 
  &:nth-of-type(even) > ${Content} {
    grid-area: left;
  }

  & > ${Content}, 
  &:nth-of-type(even) > ${Image} {
    grid-area: right;
  }
`;

这里是最小的codesandbox


或者,您可以考虑只使用一个网格:

const Inner = styled.div`
  display: grid;
  grid-template-columns: repeat(2, 1fr);
`;

const Image = styled.img`
  grid-column: 1;
  &:nth-of-type(even) {
    grid-column: 2;
  }
`;

const Content = styled.div`
  grid-column: 2;
  &:nth-of-type(even) {
    grid-column: 1;
  }
`;

// use fragment (<>) so box is not rendered as a div
const Box = ({ content }) => (
  <>
    <Image src="https://via.placeholder.com/100x100" />
    <Content>{`item ${content}`}</Content>
  </>
)

另一个codesanbox

答案 1 :(得分:0)

知道了!

这对我有用:

import React, { Component } from "react";
import { Link, graphql, StaticQuery } from 'gatsby'
import styled from 'styled-components'
import Img from 'gatsby-image'

const Wrapper = styled.div`
    margin: 0 auto;
    margin-bottom: 6rem;
    overflow: visible;
` 

const Title = styled.h5`
    margin-bottom: 2rem;
    text-align: center;
`

const Inner = styled.div`
    display: grid;
    grid-template-columns: 1fr;
    grid-row-gap: 3rem;

    @media (max-width: 1048px) {
        grid-template-columns: 1fr 1fr;
    }

    @media (max-width: 800px) {
        grid-template-columns: 1fr;
    }
`

const Box = styled.div`
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 3rem;
    align-items: center; 

    ${Inner} &:nth-child(even) {
        grid-template-areas: 
        "right left";
    }

    ${Inner} &:nth-child(odd) {
        grid-template-areas: 
        "left right";
    }
`

const Thumb = styled(Link)`
    text-decoration: none;
    color: inherit;
    grid-area: left;
`

const Content = styled.div`
    text-decoration: none;
    grid-area: right;
`

const StyledLink = styled(Link)`
    text-decoration: none;
    color: inherit;
`

const StyledImg = styled(Img)`
    border-radius: 7px;
    margin-bottom: 1rem;
    opacity: 1;
    -webkit-transition: .5s ease-in-out;
    transition: .5s ease-in-out;

        :hover {
            opacity: .7;
        }
`

const PostTitle = styled.h6`
    margin-bottom: 0.5rem;

`

const Date = styled.p`  
    font-size: 0.8rem;
    display: block;
    color: #777;

`

export class Gallery extends Component {

      render(){
        return (
            <Wrapper>
            <Title>
                Works
            </Title>
                <Inner>
                {this.props.data.allMarkdownRemark.edges.map(({ node }) => (
                    <Box key={node.id} className='box' >
                        <Thumb to={node.fields.slug}>
                            <StyledImg fluid={node.frontmatter.image.childImageSharp.fluid} />
                        </Thumb> 
                        <Content>
                            <StyledLink to={node.fields.slug}>
                                <PostTitle>
                                    {node.frontmatter.title}{" "}
                                </PostTitle>
                            </StyledLink>
                            <Date>
                            {node.frontmatter.date}
                            </Date>
                            <p>{node.excerpt}</p>
                        </Content>
                    </Box>
                ))}
                </Inner>
            </Wrapper>
        )
    }
}

export default props => (

    <StaticQuery
    query={graphql`
      query {
          allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) {
              totalCount
              edges {
              node {
                  id
                  frontmatter {
                  title
                  date(formatString: "DD MMMM, YYYY")
                  image {
                  childImageSharp {
                      fluid(maxWidth: 800) {
                      ...GatsbyImageSharpFluid
                        base64
                        tracedSVG
                        aspectRatio
                      }
                  }
              }
                  }
                  fields {
                  slug
                  }
                  excerpt
              }
              }
          }
          }
    `}
    render={data => <Gallery data={data} {...props} />}
    />
)

谢谢!