Fruits Style the Application
Learning objective : By the end of this lesson, students will be able to enhance the user experience of their full-stack applications by effectively integrating CSS styling through the use of static files.
Now that we’ve got a fully functional app, it’s time to add some styling! These steps are divided into labelled sections, so feel free to follow along for as much or as little as you’d like. If you do choose to complete all the sections, you’ll have a fully styled app by the end of this level up.
Setting up the styleshets
-
Create the following folders in your project directory:
publicandpublic/stylesheets:mkdir public public/stylesheets -
In your
server.jsfile, add the following middleware to serve static files from the directory:app.use(express.urlencoded({ extended: false })); app.use(methodOverride("_method")); // app.use(morgan('dev')); // new code below this line app.use(express.static(path.join(__dirname, "public"))); // new code above this line app.get("/", async (req, res) => { res.render("index.ejs"); }); -
Require the
pathmodule at the top of yourserver.jsfile:const methodOverride = require("method-override"); const morgan = require("morgan"); // new code below this line const path = require("path"); -
Create a CSS a
style.cssfile within thestylesheetsfolder:touch public/stylesheets/style.css
Basic Styling
-
Link the
style.cssfile to all of your ejs pages by adding the following code within the<head>section of your pages:<!-- all template pages --> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> // new code below this line <link rel="stylesheet" href="/stylesheets/style.css" /> </head> -
Import our font from Google Fonts into
style.cssat the very top of the stylesheet:@import url("https://fonts.googleapis.com/css2?family=DM+Sans:opsz@9..40&display=swap"); -
Add an image to the
index.ejspage:<!-- index.ejs homepage --> <body> <h1>Welcome to the Fruits app!</h1> // new code below this line <img class="fruit-pic1" src="https://cdn-icons-png.flaticon.com/128/5312/5312448.png" alt="happy fruit salad bowl" /> //new code above this line <p>An app for collecting your favorite fruits.</p> </body> -
Add a footer to the bottom of
index.ejs, under the closing</body>tag (we’ll use this to attribute the icon we’re using for this app):<!-- index.ejs homepage --> </body> // new code below this line <footer>Icons by <a href="https://www.flaticon.com/authors/freepik">Freekpik</a></footer> -
Add the following basic styles to style.css:
body { background: #fff8ed; font-family: "DM Sans", sans-serif; display: flex; flex-direction: column; align-items: center; justify-content: center; max-width: 100vw; } h1 { color: #769642; font-size: 3.6em; } footer { font-size: 0.7em; position: fixed; left: 0; bottom: 0; width: 100%; text-align: center; padding: 10px; } .fruit-pic1 { height: 30%; }
Styling links
-
Modify the
<a>tag onindex.ejsto include a class calledfruits-index-link:<!-- index.ejs fruits --> <a class="fruits-index-link" href="/fruits">Browse Fruits</a> -
Wrap the text of that same
<a>tag in a<div>with the class name ofindex-link-text. Do this for all links in the app that say “Back to Fruits” (on thefruits/edit.ejsandfruits/show.ejspages):<!-- edit.ejs / show.ejs --> <a class="fruits-index-link" href="/fruits"> <div class="index-link-text">Back to Fruits</div> </a> -
Add the following style rules to
style.css:.fruits-index-link { text-decoration: none; } .index-link-text { background-color: #f47b5b; color: white; font-size: 1.4em; width: 10em; padding: 5px 15px; margin: 15px; border-radius: 25px; text-align: center; box-shadow: 0 5px #ffbd59; } .index-link-text:hover { background-color: #ffbd59; box-shadow: 0 5px #f47b5b; } .index-link-text:active { background-color: #f47b5b; box-shadow: 0 2.5px #ffbd59; }
Styling forms
-
On
new.ejsandedit.ejs, add a<div>around the<label>and<input>forready to eat, and apply the classcheckbox-div:<!-- new.ejs / edit.ejs --> <div class="checkbox-div"> <label for="ready-to-eat">Ready to Eat?</label> <input type="checkbox" name="isReadyToEat" id="ready-to-eat" /> </div> -
Add the following CSS to
style.css:form { font-family: "DM Sans", sans-serif; display: flex; flex-direction: column; justify-content: center; align-items: flex-start; background-color: #ffbd59; padding: 20px 30px; border-radius: 20px; box-shadow: 5px 6px #f47b5b; margin: 20px 10px; } .checkbox-div { flex-direction: row; } label, input { margin: 10px 2px 0 2px; } button { align-self: center; margin: 10px 4px 4px 4px; background-color: #3f6a51; color: white; padding: 5px 10px; border-radius: 15px; border: none; width: 15em; } button:hover { background-color: #769642; } button:active { background-color: #2d4d3a; }
Styling show.ejs
-
On
show.ejsadd a<div>around the content, buttons, and links, and apply the classfruit-details:<!-- show.ejs --> <body> <div class="fruit-details"> <!-- show page content --> </div> <a class="fruits-index-link" href="/fruits"> <div class="index-link-text">Back to Fruits</div> </a> </body> -
Add a second
<div>around thedeleteform andeditlink, and give it a class offruit-actions:<div class="fruit-actions"> <form class="delete-form" action="/fruits/<%=fruit._id%>?_method=DELETE" method="POST" > <button class="delete-button" type="submit"> Delete <%= fruit.name %> </button> </form> <a class="edit-link" href="/fruits/<%= fruit._id %>/edit"> <div class="edit-text">Edit <%= fruit.name %></div> </a> </div> -
Add the following CSS to
style.css:.fruit-actions { display: flex; flex-direction: row; justify-content: center; align-items: center; width: 100%; height: 130px; padding: 20px 0; } .delete-form { padding: 0; box-shadow: 0 0; background-color: transparent; height: 50px; margin: 0 20px 0 0; min-height: 100%; } .delete-button { background-color: #f47b5b; text-transform: uppercase; padding: 40px 15px; width: 70%; /* height: 100%; */ font-size: 1.3em; margin: 0; min-height: 100%; } .edit-link { text-decoration: none; } .edit-text { background-color: #3f6a51; text-transform: uppercase; padding: 40px 15px; font-size: 1.3em; border-radius: 15px; display: flex; justify-content: center; align-items: center; color: white; font-weight: bold; text-align: center; width: 70%; height: 50px; } .delete-button:hover { background-color: #ffbd59; } .delete-button:active { background-color: rgb(217, 108, 78); } .edit-text:hover { background-color: #769642; } .edit-text:active { background-color: #2d4d3a; background-color: rgb(217, 108, 78); }
Styling fruits/index.ejs
-
Modify the HTML structure on
fruits/index.ejsto create a header<div>and wrap the fruit names in cards:<!-- index.ejs --> <body> <div class="index-header-div"> <h1>All Fruits</h1> <a class="add-fruit" href="/fruits/new">Add fruit</a> </div> <ul> <% fruits.forEach((fruit)=> { %> <li> <a class="fruit-cards" href="/fruits/<%=fruit._id%>"> <%= fruit.name %> </a> </li> <% }) %> </ul> </body> -
Add class name to the
Add fruitlink calledadd-fruit:<a class="add-fruit" href="/fruits/new">Add fruit</a> -
Add the following styles to
style.css:/* index styling */ ul { display: flex; flex-wrap: wrap; } li { list-style: none; } .fruit-cards { display: flex; flex-direction: column; text-decoration: none; color: black; width: 40px; height: 70px; background-color: white; margin: 10px 15px; padding: 30px 50px; border-radius: 15px; align-items: center; justify-content: center; border: 2.5px solid #ffbd59; } .fruit-cards:hover { border: 4px solid #f47b5b; } .fruit-cards:active { background-color: #a4cf5f67; border: 2.5px solid #ffbd59; color: gray; } .index-header-div { display: flex; flex-direction: row; justify-content: space-between; align-items: center; width: 98%; } .add-fruit { display: flex; justify-content: center; align-items: center; margin: 0 20px; text-decoration: none; width: 6em; text-transform: uppercase; background-color: #769642; border-radius: 30px; color: white; padding: 10px; font-weight: bold; font-size: 1.2em; } img { height: 100%; margin: 20px 0 0 0; }
Congrats! You have a fully styled app!