Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
July 22, 2022 11:37 pm GMT

A Guide on Using Styled Components to Style all of your Blog Posts.

This is lesson 7 in a tutorial on how to create a blog using NextJS, Sanity, and Vercel.
If you are just here for help with Styled Components then you will need to implement your own text for the elements or follow my guide from lesson 1.

  • I also have a link to a working sandbox of this code in my Preview section that includes text data you can use instead.
  • I didn't implement responsiveness for small screens, but that's easy enough to handle yourself.

I've done some tweaking to the props we fetch. I will explain that part after the Planning, so if you just want Styled Components, you can skip ahead.
You should also create additional posts (at least have 2 in total) to see our Recent Posts sidebar.

Planning

It is never a good idea to style from your code. What I mean is, you should have an idea ahead of time on how you want things to look (even sketch it out), then replicate that with your code.

On the topic of 'sketching it out', I did just that. In only a couple of minutes I was able to create this Figma design.

You might need to signup to view it if you don't have a Figma account, but it's worth it to have one. The amount of time you save by sketching things out cannot be understated.

I didn't make the most complex UI ever, but it's perfectly fine for our needs. You can also click each element and see it's name (purpose) on the left hand side of the screen under Layers > Desktop-1.

One of the elements is called Social Media Buttons, so we are going to go ahead and install an npm package that is standard for almost every project.

In the command line of your project, run

npm i react-icons --save &&npm i react-portable-text

Reading the React Icons docs will explain how to use it and let you search for any icon you want. All we have to do is find the code for the icon we want, import it, and insert it like a React component.

React Portable Text is what we are going to use to display the body value we couldn't use in the last lesson.

Table of Contents

I don't know of the best way to show all of my code. I don't want to host it incase it changes later, so unfortunately the best way I can think of is to just slap it here in blocks.

But I am going to break it down into 4 parts.

  1. Imports
    • The couple of imports we need for our page
  2. Styled Components
    • Our Styled Components (done in file, not imported)
  3. HTML Structure
    • Our HTML layout with content
  4. Props
    • Changes to our getStaticProps
  5. Preview
    • Online sandbox so you can see how it should look or copy the /pages/posts/[slug].js file.

Imports

This can look different for you if you choose to use additional icons, I'm just importing 3 basic ones for now.

import PortableText from "react-portable-text";import styled from "styled-components";import Link from "next/link";import { BsFacebook, BsTwitter, BsInstagram } from "react-icons/bs";

We import..

  • PortableText to display the body of our post.
  • styled so we can create styled components.
  • Link to navigate to the homepage or to other posts.
  • The last line is importing a Facebook, Twitter, and Instagram icon from our react-icons.

Styled Components

FYI: I only spent a little over an hour on the styling. It isn't perfect and some of the code is redundant, but I'm already behind on this project so I just wanted to get something that looked nice in browser.

Before we get to the components, I added a couple things to our /styles/globals.css file.

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');* {  padding: 0;  margin: 0;  font-family: 'Poppins';  color: #333;}body {  background: rgb(248, 248, 248)}a {  color: inherit;  text-decoration: none;}* {  box-sizing: border-box;}
  • Poppins is now our default font for everything.
  • #333 is the default font color for everything.
  • The body now has a background color of rgb(248, 248, 248).
    • This is an off white color that is easier on the eyes.

Below your imports but above your Post component is where we will create our styling. Normally this is done in separate files, but since we aren't styling that many pages I don't see a reason to break it up.

I explained Styled Components very briefly at the start of these guides, but I will go over 1 I created for this page as a refresher.

Do not copy this into your file yet, it will be included in the full list of components I will post after this explanation.

const BackButton = styled.div`  border: 1px solid #333;  border-radius: 7px;  text-align: center;  font-size: 1.2rem;  width: fit-content;  padding: 4px 6px;  transition: all 0.3s;  :hover {    background: #333;    color: white;    cursor: pointer;  }  span {    position: relative;    bottom: 3px;  }`;
  • First we create a component with the name of BackButton

    • This is a React component so it must be Pascal case (each word capital).
  • We declare that this component is a styled.div

    • styled. is from our import
    • div is letting React know what kind of HTML element we are assigning. in this case it will be a <div></div>
    • All you have to do to use it is replace <div></div> in your code for <BackButton></BackButton> and it will now be a div element with styling.
  • You also need to be aware that we are wrapping the CSS for our component in backticks.

  • Now inside is our basic CSS. I'm not going to go over the details of my CSS, or how I'm using grid for positioning because it's better for you to play around with it and find out yourself. But if you still do not understand the purpose of a line, you can either Google it, play around with it in your Browser DevTools, or even shoot me a message and I can help explain further.

    • We apply styling to our div element
    • What happens when the div is hovered
    • And finally we apply styling to any span elements inside of this div.

After that quick example, here is the entire block of code for all of our styling. Remember, paste this below your imports and above your Post component.

const PageContainer = styled.div`  padding: 70px 110px;`;const BackButton = styled.div`  border: 1px solid #333;  border-radius: 7px;  text-align: center;  font-size: 1.2rem;  width: fit-content;  padding: 4px 6px;  transition: all 0.3s;  :hover {    background: #333;    color: white;    cursor: pointer;  }  span {    position: relative;    bottom: 3px;  }`;const ContentContainer = styled.div`  display: grid;  grid-template-columns: 1fr 2fr 1fr;  grid-template-rows: 1fr auto;  grid-template-areas:    "header header header"    "socials main links";`;const Header = styled.header`  grid-area: header;  text-align: center;  margin-bottom: 40px;  h1 {    text-transform: uppercase;    color: #000000;    font-size: 3rem;  }  span {    color: #464646;  }`;const SocialsContainer = styled.ul`  grid-area: socials;  display: flex;  flex-direction: column;  align-items: end;  list-style-type: none;  gap: 30px;  padding-right: 50px;  padding-top: 14px;  li {    cursor: pointer;  }`;const StyledLi = styled.li`  svg {    transition: transform 0.4s;  }  svg:hover {    transform: scale(1.2);  }`;const Body = styled.main`  grid-area: main;  h1 {    text-align: center;    font-size: 2.3rem;    margin-bottom: 15px;  }  h2 {    margin: 5px 0px;  }  div {    display: flex;    flex-direction: column;    gap: 5px;  }`;const RecentPostsContainer = styled.div`  padding-left: 50px;  grid-area: links;  display: flex;  flex-direction: column;  gap: 20px;`;const RecentPost = styled.div`  display: flex;  flex-direction: column;  border: 1px solid #333;  align-items: center;  transition: all 0.4s;  p {    font-size: 1.1rem;    font-weight: 500;  }  span,  p {    transition: all 0.4s;  }  :hover {    background: #333;    cursor: pointer;    span,    p {      color: white;    }  }`;

I'm styling the post.body content from within the Body component.
As you can see I only targeted h1, h2, and div because those are what I have inside of my post's body. If you have other elements you can style them how you see fit, by targeting the type of the element and applying your style.

HTML Structure

Pasting all of that in won't do a darn thing until you add these components to your code.

Remember, your code will break because I changed how we import our posts. That will be explained next.

export default function Post({ post, posts }) {  const postsElements = posts.map((post, index) => (    <Link key={index} href={`/posts/${post.slug}`}>      <RecentPost>        <p>{post.title}</p>        <span>{new Date(post.publishedAt).toDateString().slice(4)}</span>      </RecentPost>    </Link>  ));  return (    <PageContainer>      <Link href={`/`}>        <BackButton>          <span></span>          <a>Home</a>        </BackButton>      </Link>      <ContentContainer>        <Header>          <span>{new Date(post.publishedAt).toDateString()}</span>          <h1>{post.title}</h1>        </Header>        <SocialsContainer>          <StyledLi>            <a href="https://facebook.com">              <BsFacebook size={"3rem"} />            </a>          </StyledLi>          <StyledLi>            <a href="https://twitter.com">              <BsTwitter size={"3rem"} />            </a>          </StyledLi>          <StyledLi>            <a href="https://instagram.com">              <BsInstagram size={"3rem"} />            </a>          </StyledLi>        </SocialsContainer>        <Body>          <PortableText content={post.body} />        </Body>        <RecentPostsContainer>{postsElements}</RecentPostsContainer>      </ContentContainer>    </PageContainer>  );}

This is pretty simple, we are using our Styled Components we just created instead of normal HTML elements.

I will point out the couple of things that are important to take note of here.

  • export default function Post({ post, posts })
    • You can see we are now importing post AND posts. You will see why in a second.
const postsElements = posts.map((post, index) => (    <Link key={index} href={`/posts/${post.slug}`}>      <RecentPost>        <p>{post.title}</p>        <span>{new Date(post.publishedAt).toDateString().slice(4)}</span>      </RecentPost>    </Link>  ));
  • We are mapping over the posts we fetch to create a list of links to every post (excluding the post we are currently viewing).

    • <BsFacebook size={"3rem"} />
  • React Icons are styled by this size attribute so we have these on each one to increase them to 3rem.

<Body>    <PortableText content={post.body} /></Body>
  • You can see our PortableText we imported being used to display the body of our post by adding it as the content.
  • It's annoying to style PortableText, so I just surround it in a styled div and apply the styling there.

    • <RecentPostsContainer>{postsElements}</RecentPostsContainer>
  • You can see our postsElements variable we created being surrounded by a styled component.

Props

I came up with the idea to display all of our blog posts in the right sidebar. Before we were only fetching our current post, but now we need to fetch all of them as well.

export async function getStaticProps({ params }) {  const query = `*[_type == "post"] {    _id,    title,    publishedAt,    'slug': slug.current,    body  }`;  let posts = await client.fetch(query);  const post = await posts.find((post) => post.slug == params.slug);  posts.splice(    posts.indexOf(posts.find((post) => post.slug == params.slug)),    1  );  return {    props: { posts, post },  };}

Not a lot changed, but I'll explain the general idea of it.

  • We no longer fetch just the current post, we now get every single entry with a type of post.

  • After all of our posts are returned, we run a find method to match the post in our array the contains the same slug as our url params.

  • Then we splice out the post we just fetched because we don't want to display that one in our list of posts on the side.

  • Finally we return all of our posts excluding our current post, and our current post.

Preview

CodeSandbox Code -- Fullscreen Preview
Here you can view my code, there are some changes to remove fetching and the file structure is obviously incorrect. This is supposed to just be a reference to how the page and /pages/posts/[slug].js code should look for you (minus the slight changes).

That's the end of this part. We didn't alter our project too much, but we now have a great looking page to display each of our posts.

I know that was a lot of code, and there is always a possibility something goes wrong on your end. So if there is something you just cannot seem to fix, send me a message and I will help you out as much as I can.

Next Lesson

I think I will skip styling the homepage for now. It would be a fantastic exercise to practice styled components.

At the end of the tutorial I'll have a link to this project which will include my personal styling if you are interested in that.

The next few lessons are going to be less code oriented and more involved with using Vercel, GitHub, and Sanity utilities.
Our goal is to...

  1. Push our code to GitHub.

  2. Deploy our website on Vercel.

  3. Deploy our Sanity Studio interface to Vercel.

Thank you to everyone who was read these lessons!


Original Link: https://dev.to/zacherymorgan/a-guide-on-using-styled-components-to-style-all-of-your-blog-posts-3ofj

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To