├── .gitignore ├── Desktop-Version.PNG ├── mobile version.PNG ├── modules ├── mydate.js ├── variables.js ├── menu.js └── bookClass.js ├── .hintrc ├── .eslintrc.json ├── .stylelintrc.json ├── js └── index.js ├── package.json ├── MIT.md ├── .github └── workflows │ └── linters.yml ├── index.html ├── README.md └── css └── index.css /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /Desktop-Version.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chrissiku/Awesome-Books/HEAD/Desktop-Version.PNG -------------------------------------------------------------------------------- /mobile version.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chrissiku/Awesome-Books/HEAD/mobile version.PNG -------------------------------------------------------------------------------- /modules/mydate.js: -------------------------------------------------------------------------------- 1 | import { DateTime } from '../luxon.js'; 2 | 3 | const dateTime = DateTime.now().toFormat('LLL dd yyyy, hh:mm:ss a'); 4 | document.getElementById('date').innerHTML = Date(); 5 | 6 | export default dateTime; 7 | -------------------------------------------------------------------------------- /.hintrc: -------------------------------------------------------------------------------- 1 | { 2 | "connector": { 3 | "name": "local", 4 | "options": { 5 | "pattern": ["**", "!.git/**", "!node_modules/**"] 6 | } 7 | }, 8 | "extends": ["development"], 9 | "formatters": ["stylish"], 10 | "hints": [ 11 | "button-type", 12 | "disown-opener", 13 | "html-checker", 14 | "meta-charset-utf-8", 15 | "meta-viewport", 16 | "no-inline-styles:error" 17 | ] 18 | } -------------------------------------------------------------------------------- /modules/variables.js: -------------------------------------------------------------------------------- 1 | const bookTitle = document.querySelector('#book-title'); 2 | const bookAuthor = document.querySelector('#book-author'); 3 | const addBookBtn = document.querySelector('#add'); 4 | const bookList = document.querySelector('#bookList'); 5 | 6 | // Initialise the collection of books 7 | 8 | const collectBooks = JSON.parse(localStorage.getItem('books')) || []; 9 | 10 | export { 11 | bookTitle, bookAuthor, addBookBtn, bookList, collectBooks, 12 | }; 13 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true, 5 | "jest": true 6 | }, 7 | "parser": "babel-eslint", 8 | "parserOptions": { 9 | "ecmaVersion": 2018, 10 | "sourceType": "module" 11 | }, 12 | "extends": ["airbnb-base"], 13 | "rules": { 14 | "no-shadow": "off", 15 | "no-param-reassign": "off", 16 | "eol-last": "off", 17 | "import/extensions": [ 1, { 18 | "js": "always", "json": "always" 19 | }] 20 | }, 21 | "ignorePatterns": [ 22 | "dist/", 23 | "build/" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["stylelint-config-standard"], 3 | "plugins": ["stylelint-scss", "stylelint-csstree-validator"], 4 | "rules": { 5 | "at-rule-no-unknown": [ 6 | true, 7 | { 8 | "ignoreAtRules": ["tailwind", "apply", "variants", "responsive", "screen"] 9 | } 10 | ], 11 | "scss/at-rule-no-unknown": [ 12 | true, 13 | { 14 | "ignoreAtRules": ["tailwind", "apply", "variants", "responsive", "screen"] 15 | } 16 | ], 17 | "csstree/validator": true 18 | }, 19 | "ignoreFiles": ["build/**", "dist/**", "**/reset*.css", "**/bootstrap*.css", "**/*.js", "**/*.jsx"] 20 | } 21 | -------------------------------------------------------------------------------- /modules/menu.js: -------------------------------------------------------------------------------- 1 | const myMenu = () => { 2 | const menu = document.querySelectorAll('.menu-item '); 3 | const contents = document.querySelectorAll('.page_content'); 4 | // Display tabulation 5 | menu.forEach((menuItem, index) => { 6 | menuItem.addEventListener('click', () => { 7 | contents.forEach((content) => { 8 | content.classList.remove('active'); 9 | }); 10 | menu.forEach((menuItem) => { 11 | menuItem.classList.remove('active'); 12 | }); 13 | contents[index].classList.add('active'); 14 | menu[index].classList.add('active'); 15 | }); 16 | }); 17 | }; 18 | 19 | export default myMenu; 20 | -------------------------------------------------------------------------------- /js/index.js: -------------------------------------------------------------------------------- 1 | import myMenu from '../modules/menu.js'; 2 | import { 3 | BookClass, 4 | bookTitle, 5 | bookAuthor, 6 | addBookBtn, 7 | // collectBooks, 8 | } from '../modules/bookClass.js'; 9 | import myDateTime from '../modules/mydate.js'; 10 | 11 | const collectionBooks = JSON.parse(localStorage.getItem('books')) || []; 12 | 13 | const myBookList = new BookClass(); 14 | 15 | // Button to add new book to the collection 16 | 17 | addBookBtn.addEventListener('click', () => { 18 | myBookList.addBook(); 19 | bookTitle.value = ''; 20 | bookAuthor.value = ''; 21 | localStorage.setItem('books', JSON.stringify(collectionBooks)); 22 | myBookList.displayBooks(); 23 | }); 24 | 25 | window.addEventListener('DOMContentLoaded', () => { 26 | myBookList.displayBooks(); 27 | }); 28 | 29 | myMenu(); 30 | 31 | document.getElementById('date').innerHTML = myDateTime; 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "babel-eslint": "^10.1.0", 4 | "eslint": "^7.32.0", 5 | "eslint-config-airbnb-base": "^14.2.1", 6 | "eslint-plugin-import": "^2.26.0", 7 | "hint": "^6.2.0", 8 | "stylelint": "^13.13.1", 9 | "stylelint-config-standard": "^21.0.0", 10 | "stylelint-csstree-validator": "^1.9.0", 11 | "stylelint-scss": "^3.21.0" 12 | }, 13 | "name": "awesome-books", 14 | "description": "![](https://img.shields.io/badge/Microverse-blueviolet)", 15 | "version": "1.0.0", 16 | "main": "index.js", 17 | "scripts": { 18 | "test": "echo \"Error: no test specified\" && exit 1" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/Chrissiku/Awesome-Books.git" 23 | }, 24 | "keywords": [], 25 | "author": "", 26 | "license": "ISC", 27 | "bugs": { 28 | "url": "https://github.com/Chrissiku/Awesome-Books/issues" 29 | }, 30 | "homepage": "https://github.com/Chrissiku/Awesome-Books#readme" 31 | } 32 | -------------------------------------------------------------------------------- /MIT.md: -------------------------------------------------------------------------------- 1 | ## Copyright 2021, [YOUR NAME] 2 | 3 | ###### Please delete this line and the next one 4 | ###### APP TYPE can be a webpage/website, a web app, a software and so on 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this [APP TYPE] and associated documentation files, to deal in the [APP TYPE] without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the [APP TYPE], and to permit persons to whom the [APP TYPE] is furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the [APP TYPE]. 9 | 10 | THE [APP TYPE] IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE [APP TYPE] OR THE USE OR OTHER DEALINGS IN THE [APP TYPE]. 11 | -------------------------------------------------------------------------------- /.github/workflows/linters.yml: -------------------------------------------------------------------------------- 1 | name: Linters 2 | 3 | on: pull_request 4 | 5 | env: 6 | FORCE_COLOR: 1 7 | 8 | jobs: 9 | lighthouse: 10 | name: Lighthouse 11 | runs-on: ubuntu-18.04 12 | steps: 13 | - uses: actions/checkout@v2 14 | - uses: actions/setup-node@v1 15 | with: 16 | node-version: "12.x" 17 | - name: Setup Lighthouse 18 | run: npm install -g @lhci/cli@0.7.x 19 | - name: Lighthouse Report 20 | run: lhci autorun --upload.target=temporary-public-storage --collect.staticDistDir=. 21 | webhint: 22 | name: Webhint 23 | runs-on: ubuntu-18.04 24 | steps: 25 | - uses: actions/checkout@v2 26 | - uses: actions/setup-node@v1 27 | with: 28 | node-version: "12.x" 29 | - name: Setup Webhint 30 | run: | 31 | npm install --save-dev hint@6.x 32 | [ -f .hintrc ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/html-css-js/.hintrc 33 | - name: Webhint Report 34 | run: npx hint . 35 | stylelint: 36 | name: Stylelint 37 | runs-on: ubuntu-18.04 38 | steps: 39 | - uses: actions/checkout@v2 40 | - uses: actions/setup-node@v1 41 | with: 42 | node-version: "12.x" 43 | - name: Setup Stylelint 44 | run: | 45 | npm install --save-dev stylelint@13.x stylelint-scss@3.x stylelint-config-standard@21.x stylelint-csstree-validator@1.x 46 | [ -f .stylelintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/html-css-js/.stylelintrc.json 47 | - name: Stylelint Report 48 | run: npx stylelint "**/*.{css,scss}" --fix 49 | eslint: 50 | name: ESLint 51 | runs-on: ubuntu-18.04 52 | steps: 53 | - uses: actions/checkout@v2 54 | - uses: actions/setup-node@v1 55 | with: 56 | node-version: "12.x" 57 | - name: Setup ESLint 58 | run: | 59 | npm install --save-dev eslint@7.x eslint-config-airbnb-base@14.x eslint-plugin-import@2.x babel-eslint@10.x 60 | [ -f .eslintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/html-css-js/.eslintrc.json 61 | - name: ESLint Report 62 | run: npx eslint . --fix 63 | -------------------------------------------------------------------------------- /modules/bookClass.js: -------------------------------------------------------------------------------- 1 | // Declaration of my items in he DOM 2 | const bookTitle = document.querySelector('#book-title'); 3 | const bookAuthor = document.querySelector('#book-author'); 4 | const addBookBtn = document.querySelector('#add'); 5 | const bookList = document.querySelector('#bookList'); 6 | 7 | // // Initialise the collection of books 8 | 9 | let collectBooks = JSON.parse(localStorage.getItem('books')) || []; 10 | 11 | // Display the current date 12 | 13 | // Create a class to store books 14 | class BookClass { 15 | // Create class constructor 16 | 17 | Constructor(title, author) { 18 | this.bookTitle = title; 19 | this.bookAuthor = author; 20 | } 21 | 22 | // Add the method to add new book to the localStorage 23 | addBook() { 24 | this.book = {}; 25 | this.book.title = bookTitle.value; 26 | this.book.author = bookAuthor.value; 27 | collectBooks.push(this.book); 28 | } 29 | 30 | // Add the method to remove a given book to the localStorage 31 | 32 | remove(element) { 33 | this.bookId = element.target.id; 34 | this.bookToDelete = collectBooks[this.bookId - 1]; 35 | this.freshCollection = collectBooks.filter( 36 | (book) => book !== this.bookToDelete, 37 | ); 38 | collectBooks = this.freshCollection; 39 | localStorage.setItem('books', JSON.stringify(this.freshCollection)); 40 | element.target.parentElement.remove(); 41 | } 42 | 43 | // Add the method to display the whole localStorage 44 | 45 | displayBooks() { 46 | bookList.innerHTML = ''; 47 | collectBooks.forEach((element, index) => { 48 | // Define all neccessary items 49 | 50 | const parentContainer = document.createElement('div'); 51 | parentContainer.classList.add('book-card'); 52 | const titleContainer = document.createElement('span'); 53 | const authorContainer = document.createElement('span'); 54 | const removeButton = document.createElement('button'); 55 | removeButton.classList.add('btn'); 56 | const bookInfos = document.createElement('p'); 57 | bookInfos.classList.add('book-infos'); 58 | removeButton.innerText = 'Remove'; 59 | 60 | // Remove book button on Click 61 | 62 | removeButton.addEventListener('click', (e) => { 63 | this.remove(e); 64 | }); 65 | 66 | removeButton.setAttribute('id', index + 1); 67 | titleContainer.innerText = `'' ${element.title} '' by `; 68 | authorContainer.innerText = element.author; 69 | bookInfos.appendChild(titleContainer); 70 | bookInfos.appendChild(authorContainer); 71 | parentContainer.appendChild(bookInfos); 72 | parentContainer.appendChild(removeButton); 73 | 74 | bookList.append(parentContainer); 75 | }); 76 | } 77 | } 78 | 79 | export { 80 | BookClass, bookTitle, bookAuthor, addBookBtn, bookList, 81 | }; 82 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Awesome Books 8 | 9 | 16 | 17 | 18 | 19 | 20 |
21 | 28 | 35 |
36 | 37 |
38 |
The Date Here
39 |
40 |
41 |

All awesome Books

42 |
43 |
44 | 45 |
46 |

Add a new Book

47 | 48 |
49 | 50 | 57 | 58 | 65 | 66 |
67 |
68 |
69 |

Contact information

70 |
71 |

72 | Do you have any question or just want to say hello ?
73 | You can reach out to us! 74 |

75 | Chris Siku 76 | 86 |
87 |
88 |
89 |
90 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](https://img.shields.io/badge/Microverse-blueviolet) 2 | 3 | # Project Name : Awesome Books 4 | 5 | > Awesome Books is a basic website that allows users to add/remove books from a list. This project is achieved by JavaScript objects and arrays. But also I dynamically modify the DOM and add basic events. 6 | > 7 | > 8 | > In order to achieve this project I used some resources and technologies listed below : 9 | 10 | 11 | 12 | 13 | 14 | | On Desktop | On Mobile | 15 | | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 16 | | Desktop version of the project | Mobile Version | 17 | 18 | 19 | 20 | ## Built With 21 | 22 | - Major languages : JavaScript Object & HTLM 23 | - Frameworks : none 24 | - Technologies used : Github, Git and Linters 25 | 26 | ## Live Demo 27 | 28 | > Click here for the [demo](https://chrissiku.github.io/Awesome-Books/) 29 | 30 | ## Getting Started 31 | 32 | To get a local copy up and running follow these simple example steps. 33 | 34 | ### Prerequisites ♻️ 35 | 36 | - A personal computer connected to the internet; 37 | - Have a working and updated browser. 38 | - Have a local version control like git installed on your computer 39 | - Have an account on Github, as an online/remote Version Control System 40 | - Code editor (Visual studio code, sublime text, notepad++, ...) installed on your computer; 41 | - At least basic of HTML and CSS. 42 | 43 | ### Setup 🎰 44 | 45 | - Click the [me](https://github.com/Chrissiku/Awesome-Books) and you'll land on the pure repository; 46 | - click on the green (🟢) button with `Code` Inscription; 47 | - You can choose to download the project or just clone it if you are familiar with Git and Github; 48 | - Follow normal step once download in your computer and use it as it's yours. 49 | 50 | ### Install 51 | 52 | - If you are familiar with git, Run `npm install` to get all dependecies required to run the linters checks, otherwise use the downloaded project on your computer without testing files 53 | 54 | ### Run test 🧪 55 | 56 | > Run thes command bellow inside your `git bash` or command line interface. 57 | 58 | - `npx hint .` : for the `html` codebase and use of best practices. 59 | - `npx stylelint "**/*.{css,scss}"` : for the `css` codebase and use of best practices. you can add 60 | - `npx eslint .` : for the `JavaScript` codebase and use of best practices. 61 | - > Note that you can add `--fix` keyword to the command for `Css` and/or `JavaScript` to make sure that you avoid all errors comming from your `code editor` 62 | 63 | ## Author 64 | 65 | 👤 **Chris Siku (Main Author)** 66 | 67 | - GitHub: [@githubhandle](https://github.com/Chrissiku) 68 | - Twitter: [@twitterhandle](https://twitter.com/christian_siku) 69 | - LinkedIn: [LinkedIn](https://www.linkedin.com/in/chris-siku-4bb53b232/) 70 | 71 | ![Chris Siku's GitHub stats](https://github-readme-stats.vercel.app/api?username=Chrissiku&count_private=true&theme=dark&show_icons=true) 72 | 73 | 74 | 👤 **Shaquille Ndunda (Coding partner)** 75 | 76 | - GitHub: [@githubhandle](https://github.com/shaqdeff) 77 | - Twitter: [@twitterhandle](https://twitter.com/shaquillendunda) 78 | - LinkedIn: [LinkedIn](https://www.linkedin.com/in/shaquille-ndunda-b13a95107/) 79 | 80 | ![Shaquille Ndunda's GitHub stats](https://github-readme-stats.vercel.app/api?username=shaqdeff&count_private=true&theme=dark&show_icons=true) 81 | 82 | ## 🤝 Contributing 83 | 84 | Contributions, issues, and feature requests are welcome! 85 | 86 | Feel free to check the [issues page](../../issues/). 87 | 88 | ## Show your support 89 | 90 | Give a ⭐️ if you like this project! 91 | 92 | ## Acknowledgments 93 | 94 | - Microverse 95 | - Hat tip to anyone whose code was used. 96 | 97 | ## 📝 License 98 | 99 | This project is [MIT](./MIT.md) licensed. 100 | -------------------------------------------------------------------------------- /css/index.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Montserrat+Alternates:ital,wght@0,400;0,500;0,700;1,800&display=swap"); 2 | 3 | * { 4 | margin: 0; 5 | padding: 0; 6 | text-decoration: none; 7 | list-style: none; 8 | box-sizing: border-box; 9 | font-family: "Montserrat Alternates", sans-serif; 10 | color: #1d1c1c; 11 | } 12 | 13 | body { 14 | display: flex; 15 | flex-direction: column; 16 | align-items: center; 17 | 18 | /* align-items: center; */ 19 | } 20 | 21 | header { 22 | position: fixed; 23 | width: 100%; 24 | display: flex; 25 | flex-direction: column; 26 | justify-content: space-between; 27 | align-items: center; 28 | gap: 10px; 29 | padding: 10px 25px; 30 | background: #dad5d5; 31 | box-shadow: 0 2px 10px rgba(82, 80, 80, 0.384); 32 | } 33 | 34 | header a.logo { 35 | background: rgba(133, 127, 167, 0.5); 36 | display: flex; 37 | justify-content: space-around; 38 | align-items: center; 39 | gap: 10px; 40 | padding: 18px; 41 | border-radius: 50px 0 50px 0; 42 | } 43 | 44 | header a.logo i { 45 | font-size: 35px; 46 | color: rgb(219, 101, 16); 47 | } 48 | 49 | header a.logo span { 50 | font-size: 15px; 51 | font-weight: 800; 52 | text-transform: uppercase; 53 | } 54 | 55 | header nav ul.menu { 56 | display: flex; 57 | justify-content: space-between; 58 | align-items: center; 59 | padding: 10px 0; 60 | cursor: pointer; 61 | } 62 | 63 | header nav ul.menu li { 64 | text-align: center; 65 | width: 100px; 66 | padding: 5px 5px; 67 | border-radius: 20px; 68 | } 69 | 70 | header nav ul.menu li a { 71 | font-weight: 500; 72 | font-size: 13px; 73 | } 74 | 75 | header nav ul.menu li.active { 76 | background: rgba(133, 127, 167, 0.5); 77 | } 78 | 79 | main .page_content .contact ul li { 80 | color: #000; 81 | font-weight: 500; 82 | } 83 | 84 | header nav ul.menu li:hover { 85 | background: rgba(155, 141, 236, 0.5); 86 | } 87 | 88 | main .page_content .contact ul li a { 89 | color: rgb(16, 30, 219); 90 | font-weight: 500; 91 | } 92 | 93 | header nav ul.menu li.active > a { 94 | color: #000; 95 | font-weight: 600; 96 | } 97 | 98 | main { 99 | display: flex; 100 | flex-direction: column; 101 | justify-content: center; 102 | align-items: stretch; 103 | gap: 20px; 104 | margin-top: 155px; 105 | padding: 10px; 106 | } 107 | 108 | main .date { 109 | text-align: center; 110 | } 111 | 112 | main .page h3 { 113 | text-align: center; 114 | font-size: 20px; 115 | } 116 | 117 | main .page_content { 118 | display: none; 119 | } 120 | 121 | .page_content.active { 122 | display: block; 123 | } 124 | 125 | main .page_content .book-list { 126 | margin: 10px; 127 | max-height: 50vh; 128 | padding: 20px 10px; 129 | overflow: hidden; 130 | overflow-y: scroll; 131 | box-shadow: 0 5px 6px rgba(0, 0, 0, 0.329); 132 | } 133 | 134 | main .page_content .book-list .book-card { 135 | display: flex; 136 | justify-content: space-between; 137 | padding: 10px; 138 | font-size: 15px; 139 | font-weight: 600; 140 | gap: 10px; 141 | } 142 | 143 | main .page_content .book-list .book-card:nth-child(odd) { 144 | background: #dad5d5; 145 | } 146 | 147 | main .page_content form button { 148 | width: 100px; 149 | border: 1px solid green; 150 | color: #000; 151 | background: rgba(9, 255, 0, 0.199); 152 | padding: 5px; 153 | } 154 | 155 | main .page_content form button:hover { 156 | background: rgba(0, 128, 0, 0.699); 157 | } 158 | 159 | main .page_content .book-list .book-card button { 160 | padding: 0 5px; 161 | color: #000; 162 | border: none; 163 | background: rgba(255, 0, 0, 0.199); 164 | height: 20px; 165 | align-self: end; 166 | } 167 | 168 | main .page_content form { 169 | display: flex; 170 | flex-direction: column; 171 | justify-content: center; 172 | align-items: center; 173 | gap: 20px; 174 | margin-top: 20px; 175 | } 176 | 177 | main .page_content form input { 178 | padding: 5px; 179 | width: 280px; 180 | } 181 | 182 | main .page_content .contact { 183 | display: flex; 184 | flex-direction: column; 185 | justify-content: center; 186 | align-items: center; 187 | gap: 20px; 188 | margin-top: 20px; 189 | } 190 | 191 | main .page_content .contact ul { 192 | align-self: center; 193 | max-width: 300px; 194 | } 195 | 196 | main .page_content .contact .user { 197 | margin-top: 10px; 198 | font-weight: 600; 199 | } 200 | 201 | footer { 202 | position: fixed; 203 | width: 100%; 204 | height: 40px; 205 | display: flex; 206 | padding-left: 30px; 207 | align-items: center; 208 | background: #dad5d5; 209 | box-shadow: 0 2px 10px rgba(82, 80, 80, 0.384); 210 | bottom: 0; 211 | } 212 | 213 | @media only screen and (min-width: 768px) { 214 | header { 215 | flex-direction: row; 216 | justify-content: space-around; 217 | } 218 | 219 | main { 220 | margin-top: 95px; 221 | width: 80%; 222 | } 223 | } 224 | --------------------------------------------------------------------------------