在 Gatsby 中使用带有动态内容的网格模板区域

Posted

技术标签:

【中文标题】在 Gatsby 中使用带有动态内容的网格模板区域【英文标题】:Using grid-template-areas with dynamic content in Gatsby 【发布时间】:2019-07-08 23:23:36 【问题描述】:

我正在尝试使用 CSS 网格在每行上使用交替列进行布局。第一行左边是图片,右边是文字,第二行左边是文字,右边是图片,依此类推。

我尝试使用 nth-of-type,但是由于每个帖子的父节点(Box)重复,我认为这将非常困难。

问题是我无法单独联系所有孩子,因为内容来自 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 />
    />
)
````


【问题讨论】:

【参考方案1】:

使用样式组件,您可以将 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

【讨论】:

不幸的是,第一个解决方案不起作用,因为每个帖子都会生成一个新框,所以每次都保持不变。所以我认为代码必须来自上面(内部)。我将对我的代码进行一些更改以适应您的第二个建议(而且我对片段还不是很熟悉),但是您给了我一些可以使用的好主意。非常感谢! 嘿@Fadanabela,很高兴它有帮助。你看到代码框了吗? 是的,我做到了,它帮助我让它发挥作用。我刚刚发布了答案。感谢您的帮助! @Fadanabela 不客气,我不明白您为什么需要从内部组合中定位,但您设置组件的方式可能有所不同。希望你和盖茨比玩得开心! 是因为每发一个帖子,都会生成一个新的Box div,所以如果我有6个帖子,我就会有6个Box div,并且每一个网格代码都是从零开始的,所以模板区域打印好像它始终是第一行。内部 div 保持不变并且可以“计算”它的子级。我希望我能解释清楚。这是我第一次接触 Gatsby 和 GraphQL。谢谢! :)【参考方案2】:

知道了!

这对我有用:

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 />
    />
)

谢谢!!

【讨论】:

以上是关于在 Gatsby 中使用带有动态内容的网格模板区域的主要内容,如果未能解决你的问题,请参考以下文章

网格布局与侧边栏重叠

Gatsby 的 GraphQL 查询 - 具有灵活内容模型的内容设置

正确地将第二个动态模板添加到 Gatsby/NetlifyCMS - 我哪里出错了?

如何在扩展另一个文件的 django 模板中使用带有动态内容的 html 块片段?

基于许多内容引用使用 Gatsby 动态创建页面

如何在 2 列中动态构建内容