Introduction
In this article, we use emotion css to design card templates in Nextjs that can be used as business cards. We demonstrate the manipulation of coloring css grids to come up with a beautiful structure flexible to any developer to use for a business venture e.g as a business card template. Based on preference, the colors can be changed and the information grid layout merged in any possible manner. Let's begin!
Codesandbox
The completed project is available on Codesandbox.
You can find the full codebase on my Github
Prerequisites
Entry-level knowledge in javascript and React/Nextjs and css.
Setting Up the Sample Project
Use npx create-next-app card-design
to create a Next.js project and head to the directory using `cd card design
We begin with the backend setup. The backend involves integrating Cloudinary for media upload. We'll use our backend code to upload generated card templates.
Use this link to access the cloudinary login page. If you don't have an account you can create one and log into it to access your dashboard. The dashboard should contain environment variables necessary for cloudinary integration. To use these variables, go to your project root folder and create a new file names .env
.
Paste the following code and fill the blanks with your environment variables from the cloudinary dashboard.
1".env"2CLOUDINARY_CLOUD_NAME =34CLOUDINARY_API_KEY =56CLOUDINARY_API_SECRET=
Use the npm run dev
command to start your project.
Head to the pages/api
directory and create a file named upload.js
. Start by pasting the following inside
1"pages/upload"23var cloudinary = require("cloudinary").v2;45cloudinary.config({6 cloud_name: process.env.CLOUDINARY_NAME,7 api_key: process.env.CLOUDINARY_API_KEY,8 api_secret: process.env.CLOUDINARY_API_SECRET,9});
The above code configures our cloudinary environment keys and libraries. We can finally introduce a handler function to execute our POST request.
1"pages/upload"23export default async function handler(req, res) {4 if (req.method === "POST") {5 let url = ""6 try {7 let fileStr = req.body.data;8 const uploadedResponse = await cloudinary.uploader.upload_large(9 fileStr,10 {11 resource_type: "video",12 chunk_size: 6000000,13 }14 );15 url = uploadedResponse.url16 } catch (error) {17 res.status(500).json({ error: "Something wrong" });18 }1920 res.status(200).json({data: url});21 }22}
Our handler function will receive media data from the frontend, upload it and return the file's cloudinary link as a response.
Our backend is complete. Let's now design our card.
We will design our cards using emotion css. Therefore we begin by installing the necessary modules.
1npm install @emotion/react @emotion.styled
We wil be creating the necessary components and importing them where necessary.
Using css, we will create a card component and use grids to divide the component. We can then fill specific grids with colors respective to how colorful our card should look. Our project will of course include several extra components like Title
and Forms
. The article will however focus on creating the card component.
In the pages/index
directory, replace the contents with the following
1"pages/index"23export default function Home(){4 function(5 <>6 <Card1 />7 </>8 )9}
To create the card component in the return function we will use forwardref which is used to automatically pass a ref
through a component to one of its children.
start by importing forwarded
and create
and declaring our ref
variable.
Inside the Home function, create your card component and reference it in the DOM element as shown
1"pages/index"23import { forwardRef, createRef} from 'react';4export default function Home(){5 const Card1 = forwardRef((props, ref) => (6 <Card_1 ref={refOne} >78 </Card_1>9 ));10 function(11 <>12 <Card1 ref={refOne} />13 </>14 )15}
In your styles
directory, create a directory named emotion/card1.js
, and inside we start by creating a card component. Ensure to import the emotion module
before creating your component.
1"styles/emotion/card1"23import styled from "@emotion/styled";45export const Card_1 = styled.div`6 height: 220px;7 width: 390px;8 display: grid;9 grid-template-columns: 2% 96% 2%;10 grid-template-rows: 4% 92% 4%;11 position: relative;12 margin-left: 15%;13 overflow: hidden;14 box-shadow: 2px 5px 15px 0px #17161694;15 background-color: #122529;16 &:hover {17 transform: scale(1.1);18 transition: 0.3s;19 }20`;
The above code creates a card component. I put a background color for it to be visible enough. Everything else shall be done inside the card container. Ensure to import it in the index
directory for the code to run.
Below is a preview of the above
We now introduce a color grid in which we will contain our colored designs. Add the code below to the styles/emotion/card1
directory.
1"styles/emotion/card1"23export const ColorGrid = styled.div`4 display: grid;5 grid-template-columns: repeat(3, 150px);6 grid-template-rows: repeat(8, 50px);7 grid-gap: 8px;8 width: 150px;9 height: 400px;10 transform: rotate(-45deg);11`;
After importing the code above in the index
directory, include the component inside the card component as shown below
1"pages/index"23export default function Home(){4 const Card1 = forwardRef((props, ref) => (5 <Card_1 ref={refOne} >6 <ColorGrid>7 </ColorGrid>8 </Card_1>9 ));10 function(11 <>12 <Card1 ref={refOne} />13 </>14 )15}
You can view your color grid through your browser inspects section. Yor color grid should look like below:
With the color grid set up, we are ready to include our colors as we see fit. The trick is to select the specific grids and fill the background with respective colors. This article will use the color red and green for our card component.
Head to the emotion/card1
directory and add the following
1"styles/emotion/card1"234export const Black = styled.div`5 margin-left: 30%;6 background-color: #343536;7 grid-column: 2 / span 2;8 grid-row: 1 / span 3;9`;1011export const Red1 = styled.div`12 background-color: #e45e4f;13 grid-row: 2 / span 5;14`;1516export const Red2 = styled.div`17 background-color: #e45e4f;18 grid-column: 2 / span 2;19 grid-row: 4/7;20`;2122export const Green = styled.div`23 background-color: #007e67;24 grid-column: 2/4;25 grid-row: 7/9;26`;
In the code above as earlier stated. we set the property background-color
of specific grids and use the span
property to stretch the space our color occupies.
For a clearer picture of what we just did import the color components inside the index
directory and include them in your ColorGrid
. Your final card component should look like below
1"pages/index"23export default function Home(){4 const Card1 = forwardRef((props, ref) => (5 <Card_1 ref={refOne} >6 <ColorGrid>7 <Red1 />8 <Red2 />9 <Green />10 </ColorGrid>11 </Card_1>12 ));13 function(14 <>15 <Card1 ref={refOne} />16 </>17 )18}
The above code completes our card template component. It should result in a display like shown
That's it. The template above is ready to be used to design any card, for the purpose of a business card in this article we include a demonstration.
There can be several ideas respective of the developer on how information in the card can be displayed. In our case, we will build an app that captures the template above and stores it online for future reference as well as demonstrates an example of displaying information in the card.
We will also create a second card template that can be used like the card above to help[ find a clearer picture of the css grid functionalities we've learned.
In our app, a user can select one of these templates which will be saved online, and explore an example of how the templates can be used through a form that feeds information to an information grid
that will be appended on top of the card.
The final card will only be for demonstration purposes considering a developer/user can have their own ideas on how information in the card will be displayed.
Use the code below to design your form
1"pages/index"234export const FormContainer = styled.div`5 position: relative;6 width: 350px;7 height: 100%;8 border-radius: 20px;9 padding: 40px;10 background: #ecf0f3;11 box-shadow: 14px 14px 20px #cbced1, -14px -14px 20px white;12`;13export const Inputs = styled.div`14 text-align: left;15 margin-top: 10px;16`;1718export const Label = styled.h4`19 display: block;20 width: 100%;21 padding: 0;22 border: none;23 outline: none;24 box-sizing: border-box;25 margin-bottom: 4px;26 margin-top: 12px;27 font-family: 'Josefin Sans', sans-serif;28`;2930export const Input = styled.input`31 display: block;32 width: 100%;33 padding: 0;34 border: none;35 outline: none;36 box-sizing: border-box;37 background: #ecf0f3;38 padding: 10px;39 padding-left: 20px;40 height: 45px;41 font-size: 14px;42 border-radius: 50px;43 box-shadow: inset 6px 6px 6px #cbced1, inset -6px -6px 6px white;44 &:placeholder {45 color: gray;46 }47`;
Based on information you'd like to apper on your card you can use state hooks to feed data to your form which will allow it to appear on your card.
1"pages/index"234<FormContainer>5 <Inputs>6 <Label>Name</Label>7 <Input8 id="name"9 placeholder="Full Name"10 onChange={(e) => {11 setName(e.target.value);12 }}13 />14 <Label>Company / Business Name</Label>15 <Input16 id="brandname"17 placeholder="company / brand / name"18 onChange={(e) => {19 setBrand(e.target.value);20 }}21 />22 <Label>Phone Number</Label>23 <Input24 id="phonenumber"25 placeholder="070000000"26 onChange={(e) => {27 setPhoneNumber(e.target.value);28 }}29 />30 <Label>Email</Label>31 <Input32 id="email"33 placeholder="example@test.com"34 onChange={(e) => {35 setEmail(e.target.value);36 }}37 />38 <Label >Location</Label>39 <Input40 id="location"41 type="location"42 placeholder="location"43 onChange={(e) => {44 setLocation(e.target.value);45 }}46 />47 <Label >Website</Label>48 <Input49 id="website"50 type="website"51 placeholder="website"52 onChange={(e) => {53 setWebsite(e.target.value);54 }}55 />5657 </Inputs>58 </FormContainer>
Create another card component to show your final card
display demo.
After a template is selected, the background will be uploaded to cloudinary and imported to the final card
as a background. The information grid can then be appended to this background. Use the code below to create an
information grid` sample
1"styles/emotion/card1"23export const InfoGrid = styled.div`4grid-column: 2/3;5grid-row: 2/3;6z-index: 2;7width: 100%;8height: 100%;9background-color: rgba(255, 255, 255, 0.363);10box-shadow: 0px 2px 15px rgba(0, 0, 0, 0.432);11border-radius: 6px;12font-size: 0.7rem; /*12px;*/13display: grid;14grid-template-columns: 15px repeat(3, 1fr) 15px;15grid-template-rows: repeat(3, 1fr);16line-height: 1px;17margin-=top: 10px;18`;1920export const Name = styled.h2`21 grid-column: 1 / span 2;22 grid-row: 1 / span 1;23 font-size: 1.2em;24 letter-spacing: 0.1rem;25 margin-top: 15px;26 font-size: 20px;27 background: transparent;28`;293031export const Brand = styled.p`32 grid-column: 2 / span 2;33 grid-row: 1 / span 1;34 font-size: 1.2em;35 letter-spacing: 0.1rem;36 margin-top: 15%;37 margin-left: -28%;38 background: transparent;39`;4041export const Address = styled.div`42 grid-column: 1 / span 2;43 grid-row: 4;44 margin-left: -35%;45 background: transparent;46`;474849export const PhoneNumber = styled.div`50 grid-column: 3 / span 2;51 grid-row: 3;52 text-align: end;53 background: transparent;54`;5556export const Email = styled.div`57 grid-column: 3 / span 2;58 grid-row: 4;59 text-align: end;60 background: transparent;61`;6263export const CardText = styled.p`64 font-size: 1.2em;65 letter-spacing: 0.1rem;66`;676869export const Back = styled.div`70 height: 220px;71 width: 390px;72 box-shadow: 2px 5px 15px 0px #17161694;73 margin-top: 10%;74 display: flex;75 flex-wrap: wrap;76`;777879export const NameTag = styled.div`80 margin-top: 0px;81 width: 100%;82 height: 40%;83 box-shadow: 2px 5px 15px 0px #17161694;84 margin-top: 17%;85 background: rgba(255, 255, 255, 0.363)8687`;888990export const TextLg = styled.h1`91 margin: 2px;92 font-weight: 200px;93 font-size: 30px;94 font-family: 'Heebo', sans-serif;95`;9697export const TextSm = styled.p`98 margin: 2px;99 font-weight: 100px;100 font-size: 15px;101 font-family: 'Heebo', sans-serif;102`;
The codes explained above results in the grid shown below:
That's it! We have successfully designed our card template as well as demonstrated how it can be used to create a business card.
Let's try another card once more for a clearer understanding. Based on the information provided above, create a card component called Card2
inside the index
directory using forwarded
like the first card.
Create the contents of card2
inside the styles/emotion/card2.js` directory by pasting the codes below
1"emotion/card2.js"234import styled from '@emotion/styled';567export const Card_2 = styled.div`8 box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);9 display: grid;10 grid-template-columns: repeat(12, 1fr);11 grid-template-rows: repeat(4, 1fr);12 width: 390px;13 height: 220px;14 font-family: 'Trebuchet MS', sans-serif;15 &:hover {16 transform: scale(1.1);17 transition: 0.3s;18 }19`;2021export const Purple = styled.div`22 background-color: #871F78;23 grid-column: 8 / span 5;24 grid-row: 1 / span 4;25`;2627export const Yellow2 = styled.div`28 background-color: #F2B900;29 grid-column: 1 / span 7;30 grid-row: 1 / span 4;31`;3233export const Pink2 = styled.div`34 background-color: #fa001a;35 -webkit-clip-path: polygon(0% 0%, 100% 0%, 0% 100%);36 clip-path: polygon(0% 0%, 100% 0%, 0% 100%);37 grid-row: 1 / span 3;38 grid-column: 1 / span 11;39 position: relative;40 z-index: 2;41`;4243export const Dots2 = styled.div`44 background: radial-gradient(#fa001a 20%, transparent 19%),45 radial-gradient(#fa001a 20%, transparent 19%), transparent;46 background-size: 6px 6px;47 background-position: 0 0, 3px 3px;48 grid-column: 1 / span 12;49 grid-row: 3 / span 2;50 margin: 0 0 15px 20px;51 z-index: 1;52`;5354export const Intro = styled.div`55 background: black;56 color: white;57 display: flex;58 flex-direction: column;59 grid-column: 4 / span 6;60 grid-row: 2 / span 2;61 justify-content: center;62 text-align: center;63 z-index: 3;64`;6566export const FrontName = styled.p`67 letter-spacing: 1px;68 text-transform: uppercase;69 font-size: 18px;70`;7172export const FrontBrand = styled.p`73 letter-spacing: 1px;74 text-transform: uppercase;75 font-size: 8px;76 margin-top: 5px;77`;787980export const Back2 = styled.div`81 box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);82 margin-top: 6%;83 margin-left: 6%;84 display: grid;85 grid-template-columns: repeat(12, 1fr);86 grid-template-rows: repeat(12, 1fr);87 height: 215px;88 width: 100%;89 &:hover {90 transform: scale(1.1);91 }92`;9394export const BackYellow = styled.div`95 background-color: #f1ef1c;96 grid-column: 1 / span 9;97 grid-row: 1 / span 3;98`;99100export const BackTopDots = styled.div`101 background: radial-gradient(#4cc9c8 20%, transparent 19%),102 radial-gradient(#4cc9c8 20%, transparent 19%), transparent;103 background-size: 6px 6px;104 background-position: 0 0, 3px 3px;105 grid-column: 8 / span 6;106 grid-row: 2 / span 3;107`;108109export const BackInfo = styled.div`110 grid-column: 2 / span 6;111 grid-row: 5 / span 6;112`;113114export const BackName = styled.p`115 font-size: 18px;116 font-weight: bold;117 letter-spacing: 1px;118 text-transform: uppercase;119`;120121export const BackBrand = styled.p`122 font-size: 12px;123 margin-bottom: 15px;124`;125126export const BackText = styled.p`127 font-size: 12px;128 margin-bottom: 15px;129`;130131export const BackDots = styled.div`132 background: radial-gradient(#4cc9c8 20%, transparent 19%),133 radial-gradient(#4cc9c8 20%, transparent 19%), transparent;134 background-size: 6px 6px;135 background-position: 0 0, 3px 3px;136 grid-column: 1 / span 8;137 grid-row: 11 / span 2;138 z-index: 2;139`;140141export const BackkPink = styled.div`142 background-color: #fa001a;143 grid-column: 8 / span 5;144 grid-row: 10 / span 3;145`;
Import all the above components in your index
directory and include them in your card2
component like you did earlier with card1 using (<Card 1 ref={refTwo}/>
).
1"pages/index"234 const Card2 = forwardRef((props, ref) => (5 <Card_2 ref={refTwo} onClick={card2Handler} >6 <Purple />7 <Yellow2 />8 <Pink2 />9 <Dots2 />10 </Card_2>11 ));
The result of this is like below
.
That's it! Ensure to try out the article process and enjoy the experience. Happy coding!