Learn how to create a responsive shopping cart using HTML, CSS, Vue.js, and Slick.js. Follow our step-by-step guide to enhance your web development skills.
Table of Contents
Creating a shopping cart for an e-commerce site can seem daunting. However, by using HTML, CSS, Vue.js, and Slick.js, you can build a responsive and interactive shopping cart with ease. This guide will walk you through each step, from setting up the project to finalizing the shopping cart. By the end, you’ll have a fully functional shopping cart that enhances the user experience.
Source Code
Step 1 (HTML Code):
To get started, we will first need to create a basic HTML file. In this file, we will include the main structure for our shopping cart.
After creating the files just paste the following codes into your file. Make sure to save your HTML document with a .html extension, so that it can be properly viewed in a web browser.
1. Document Structure
<!DOCTYPE html>
: Specifies the document type and version of HTML (HTML5).<html lang="en">
: Defines the root of the HTML document, with the language set to English.<head>
: Contains metadata and links to external resources.<body>
: Contains the visible content of the web page.
2. Head Section
<meta charset="UTF-8">
: Sets the character encoding to UTF-8.<meta http-equiv="X-UA-Compatible" content="IE=edge">
: Ensures compatibility with Internet Explorer.<meta name="viewport" content="width=device-width, initial-scale=1.0">
: Makes the web page responsive to different screen sizes.<title>
Shopping Cart Concept</title>
: Sets the title of the web page.<link>
tags: Link to external stylesheets:- jQuery Slick carousel styles.
- Font Awesome icons.
- Google Fonts (Nunito font).
- Custom styles (styles.css).
3. Body Section
<div id="app" v-cloak="v-cloak">
: Vue.js application container with the v-cloak directive to prevent the Vue template from being displayed before it is fully compiled.
Board Section
<div class="board">
: Main container for the shopping board.<nav>
: Navigation bar with the shopping cart title and icon.<h1>
{{title}}</h1>
: Displays the title of the shopping cart application.<i class="fa fa-shopping-cart" @click="show(neaten_slick)" aria-hidden="true">
</i>
: Shopping cart icon with a click event to show the cart.<div class="items">
: Container for the list of items.<div class="item" v-for="(item,index) in items">
: Loop through items to create item elements.<div class="img" :style="{backgroundImage:'url('+ item.url +')'}">
</div>
: Displays item image as background.<p class="name">
{{item.name}}<span class="price">
${{item.price}}</span>
</p>
: Displays item name and price.<i class="minus fa fa-minus-square" @click="minus(index)" aria-hidden="true">
</i>
: Minus icon to decrease item quantity.<span>
{{item.bought}}</span>
: Displays the quantity bought.<i class="add fa fa-plus-square" @click="plus(index)" aria-hidden="true">
</i>
: Plus icon to increase item quantity.
Checkout Section
<div class="checkout"><i class="cross fa fa-times" @click="close" aria-hidden="true">
</i>
: Checkout container with close icon.<div class="boxes">
: Contains cart details and payment details.
Cart Section
<div class="cart">
: Container for cart items.
<h4>CART</h4>
: Cart heading.
<ul class="stuff">
: List of cart items.<li v-for="(item,index) in items" v-if="item.show">
: Loop through items to display cart items if they should be shown.<div class="img" :style="{backgroundImage:'url('+ item.url +')'}">
</div>
: Item image.<div class="detail">
: Item details container.<p class="name">
{{item.name}}</p>
: Item name.<p class="price">
${{item.price}}</p>
: Item price.<i class="add fa fa-plus-square" @click="plus(index)" aria-hidden="true">
</i>
: Plus icon to increase quantity.<span>
{{item.bought}}</span>
: Quantity bought.<i class="minus fa fa-minus-square" @click="minus(index)" aria-hidden="true">
</i>
: Minus icon to decrease quantity.<p class="shipping">
+ Shipping ${{shipping}}</p>
: Shipping cost.<p class="total">
Total ${{total}}</p>
: Total cost.
Payment Details Section
<div class="details">
: Container for payment details.<div class="card">
: Credit card information display.<h3>
Credit Card</h3>
: Heading.<p class="card-num">
{{card.card_number}}</p>
: Card number.<div>
<span class="expires">
{{card.expires}}</span>
<span class="ccv">
{{card.ccv}}</span>
</div>
: Expiry date and CCV.<p class="card-holder">
{{card.card_holder}}</p>
: Card holder's name.<form class="detail">
: Form for entering credit card details.<div class="item">
: Card number input.<p>
Card number</p>
<input type="number" v-model="card.card_number"/>
<div class="item">
: Card holder input.<p>
Card holder</p>
<input type="text" v-model="card.card_holder"/>
<div class="item">
: Expiry date input.<p>
Expires</p>
<input type="month" v-model="card.expires"/>
<div class="item">
: CCV input.<p>
ccv</p>
<input type="number" v-model="card.ccv"/>
<input class="submit" type="submit" value="Checkout!"/>
: Submit button.
4. External Scripts
<script src="https://cdnj..vue.min.js">
</script>
: Vue.js library.<script src="https://cdnj..jquery.min.js">
</script>
: jQuery library.<script src="https://cdnj..slick-carousel/1.6.0/slick.min.js">
</script>
: Slick carousel plugin.<script src="script.js">
</script>
: Custom JavaScript file for the application logic.
This is the basic structure of our shopping cart for an e-commerce web application using HTML, and now we can move on to styling it using CSS.
Step 2 (CSS Code):
Next, we need to style our shopping cart page by adding our CSS. This will give our shopping cart an upgraded presentation. Create a CSS file with the name of styles.css and paste the given codes into your CSS file. Remember that you must create a file with the .css extension.
Let's break down the code section by section:
1. Charset Declaration: This line specifies the character encoding for the document.
2. Styling Rules:
- Font sizes are defined for various elements within the checkout section.
- Font size is set for icons within the navigation of the app.
- Font size for submission buttons and details within the checkout section.
- Styling for images within cart items and product items, including background properties and drop-shadow effects.
- The [cloak] selector hides elements.
3. Universal Styling:
- The * selector applies these styles to all elements in the document:
- position: relative; ensures elements are positioned relative to their normal position.
- box-sizing: border-box; includes padding and border in the element's total width and height.
- font-family: Nunito, 微軟正黑體; specifies the font family, with a fallback to '微軟正黑體' for Chinese characters.
- color: #3d1f0e; sets the text color.
4. Body and HTML Styles:
- Sets width and height to 100% and hides horizontal overflow.
- Resets padding and margin for the body and HTML elements.
5. #app Styles:
- Styles for the main application container:
- Positioned absolutely and centered horizontally with a slight vertical translation.
- Rounded corners and overflow are set to hidden.
- Background image applied with sizing and repeating specified.
6. #app .board Styles:
- Styles for the board within the application:
- Similar to #app, but applied specifically to the board element.
- Background image applied with sizing and repeating specified.
7. #app .board nav Styles:
- Styles for the navigation bar within the board:
- Margin and padding are set.
- Display is flex.
- Font color is white.
8. #app .board nav i Styles:
- Styles for icons within the navigation bar:
- Positioned absolutely and shifted out of view by default.
- Color changes on hover.
9. .slick-initialized Styles:
- Visibility set to visible for initialized slick elements.
10. .items Styles:
- Styles for a container of items:
- Display is flex with wrapping.
- Height is set.
- Visibility is hidden.
11. .checkout Styles:
- Defines styles for the checkout section:
- Uses animations for a fade-in effect.
- Sets the position, size, and appearance of the checkout modal.
- Applies a background color with transparency.
- Adds a border radius for rounded corners.
12. .checkout .cross Styles:
- Styles for the close button within the checkout section:
- Positioned absolutely to the top right of the modal.
- Sets color, font weight, and cursor.
13. .checkout .boxes Styles:
- Hides elements with a blur filter and hidden visibility.
14. .checkout .slick-initialized Styles:
- Ensures visibility for initialized slick elements.
15. .checkout .slick-initialized .cart Styles:
- Styles for the cart section within the checkout modal:
- Sets padding and margin for layout.
- Styles for headings and paragraphs.
- Configures the appearance of the cart items list.
16. .checkout .slick-initialized .details Styles:
- Styles for the details section within the checkout modal:
- Sets padding for layout.
- Styles for the payment card container.
- Background image, sizing, and box-shadow applied to the card container.
- Text color and alignment for headings and card details.
- Styles for form elements and submission button.
17. Input Styles:
- Sets the background color to transparent black and defines a bottom border.
18. Keyframe Animations (Fade In):
- Defines keyframe animations for fading in elements, adjusting opacity and position over time.
19. Media Query for Small Screens:
- Adjusts styles for screens with a maximum width of 479px (typically mobile devices):
- Font sizes are reduced for various elements.
- Width, height, and positioning adjustments for the main application container (#app) and its board.
- Height adjustment for items within the board.
- Changes to navigation bar margins and padding.
- Specific adjustments to the checkout section, including minimum height and card details.
- Width adjustments for form items and submission button.
- Changes to shipping details width.
- Image width adjustments for cart items.
@charset "UTF-8";
.checkout .slick-initialized .cart .total, .checkout .cross, .slick-initialized .item .add, .slick-initialized .item .minus, .slick-initialized .item span, .slick-initialized .item p {
font-size: 1.4em;
}
#app .board nav i {
font-size: 2em;
}
.checkout .slick-initialized .details form .submit, .checkout .slick-initialized .cart ul li .detail {
font-size: 1.1em;
}
.checkout .slick-initialized .cart ul li .img, .slick-initialized .item .img {
background-size: contain;
background-repeat: no-repeat;
background-position: 50% 50%;
}
.checkout .slick-initialized .cart ul li .img, .slick-initialized .item .img {
-webkit-filter: drop-shadow(5px 5px 3px rgba(0, 0, 0, 0.5));
filter: drop-shadow(5px 5px 3px rgba(0, 0, 0, 0.5));
}
[cloak] {
display: none;
}
* {
position: relative;
box-sizing: border-box;
font-family: Nunito, 微軟正黑體;
color: #3d1f0e;
}
body, html {
width: 100%;
height: 100%;
overflow-x: hidden;
padding: 0;
margin: 0;
}
#app {
position: absolute;
width: 80%;
left: 50%;
transform: translateX(-50%) translateY(10%);
border-radius: 1em;
overflow: hidden;
background-image: url(https://s6.postimg.cc/yrm1jn9q9/chopping-board-1917996_1920.jpg);
background-size: 100% 100%;
background-repeat: no-repeat;
}
#app .board {
width: 100%;
height: 100%;
background-image: url(https://s6.postimg.cc/yrm1jn9q9/chopping-board-1917996_1920.jpg);
background-size: 100% 100%;
background-repeat: no-repeat;
}
#app .board nav {
margin: 0em 2em;
padding-top: 1em;
display: flex;
}
#app .board nav h1 {
margin: 0;
color: #fff;
font-family: Verdana;
}
#app .board nav i {
height: 7vh;
cursor: pointer;
position: absolute;
left: 100%;
transform: translateX(-100%);
color: #fff;
}
#app .board nav i:hover {
color: #ff3300;
}
.slick-initialized {
visibility: visible;
}
.items {
display: flex;
flex-wrap: wrap;
text-align: center;
height: 70vh;
visibility: hidden;
}
.slick-initialized {
visibility: visible;
}
.slick-initialized .item .img {
height: 50vh;
}
.slick-initialized .item p {
margin: 0;
margin-bottom: 0.3em;
color: #3d1f0e;
}
.slick-initialized .item p span {
font-size: 1em;
padding: 0;
padding-left: 0.3em;
color: #ff3300;
}
.slick-initialized .item span {
padding: 0 0.5em;
color: #3d1f0e;
}
.slick-initialized .item .add, .slick-initialized .item .minus {
cursor: pointer;
}
.slick-initialized .item .add:hover, .slick-initialized .item .minus:hover {
color: #ff3300;
}
.checkout {
-webkit-animation: fadeIn 1s 1;
-moz-animation: fadeIn 1s 1;
-ms-animation: fadeIn 1s 1;
-o-animation: fadeIn 1s 1;
animation: fadeIn 1s 1;
filter: blur(0em);
position: absolute;
width: 85%;
height: 85%;
left: 50%;
top: 48%;
transform: translateX(-50%) translateY(-50%);
background-color: rgba(255, 255, 255, 0.7);
z-index: 1;
border-radius: 1em;
}
.checkout .cross {
position: absolute;
left: 101%;
top: -4%;
color: white;
font-weight: 500;
cursor: pointer;
}
.checkout .boxes {
filter: blur(0em);
visibility: hidden;
}
.checkout .slick-initialized {
visibility: visible;
}
.checkout .slick-initialized .cart {
padding: 1em;
}
.checkout .slick-initialized .cart h4 {
margin: 0;
}
.checkout .slick-initialized .cart p {
text-align: right;
margin: 0;
}
.checkout .slick-initialized .cart ul {
list-style: none;
display: flex;
flex-wrap: wrap;
height: 40vh;
padding: 0.7em;
overflow-y: auto;
box-shadow: inset 0px 0px 10px 0px rgba(130, 119, 104, 0.7);
}
.checkout .slick-initialized .cart ul li {
box-shadow: 1px 1px 10px 0px #948c94;
border-radius: 0.1em;
width: 100%;
height: 15vh;
display: flex;
padding: 0.3em;
}
.checkout .slick-initialized .cart ul li .detail {
width: 80%;
text-align: right;
}
.checkout .slick-initialized .cart ul li .detail p {
margin: 0;
}
.checkout .slick-initialized .cart ul li .img {
width: 20%;
}
.checkout .slick-initialized .cart .shipping {
border-bottom: solid 2px #3d1f0e;
padding-bottom: 0.1em;
width: 40%;
margin-left: auto;
}
.checkout .slick-initialized .cart .total {
color: #ff3300;
font-weight: 700;
}
.checkout .slick-initialized .details {
padding: 1em;
}
.checkout .slick-initialized .details .card {
width: 45%;
height: 30vh;
margin: auto;
border-radius: 1em;
padding: 1em;
background-image: url(https://s6.postimg.cc/gt5mb0ttt/background-1932466_1920.jpg);
background-size: 100% 100%;
box-shadow: 0px 2px 3px rgba(107, 75, 31, 0.7);
white-space: nowrap;
}
.checkout .slick-initialized .details .card h3 {
margin: 0;
color: #fff;
text-align: right;
}
.checkout .slick-initialized .details .card .card-num {
color: #fff;
margin-bottom: 5%;
font-size: 1.4em;
}
.checkout .slick-initialized .details .card div .expires {
color: #fff;
}
.checkout .slick-initialized .details .card div .ccv {
color: #fff;
position: absolute;
left: 100%;
transform: translateX(-100%);
}
.checkout .slick-initialized .details .card .card-holder {
color: #fff;
margin-top: -0.01em;
}
.checkout .slick-initialized .details form {
width: 100%;
margin: auto;
display: flex;
flex-wrap: wrap;
margin-top: 1em;
}
.checkout .slick-initialized .details form .item {
width: 45%;
margin: 0.2em auto;
}
.checkout .slick-initialized .details form .item input {
width: 90%;
margin-right: 0.5em;
}
.checkout .slick-initialized .details form .item p {
margin: 0;
}
.checkout .slick-initialized .details form .submit {
width: 35%;
padding: 0.2em;
border: solid 0px;
border-radius: 1em;
margin: auto;
color: #3d1f0e;
background-color: #f2a841;
margin-top: 1em;
font-weight: 700;
}
.checkout .slick-initialized .details form .submit:hover {
color: #ff3300;
}
input {
background-color: rgba(0, 0, 0, 0);
border: solid 0px;
border-bottom: solid 2px;
}
@-webkit-keyframes fadeIn {
0% {
opacity: 0;
top: 55%;
}
100% {
opacity: 1;
top: 48%;
}
}
@-moz-keyframes fadeIn {
0% {
opacity: 0;
top: 55%;
}
100% {
opacity: 1;
top: 48%;
}
}
@-ms-keyframes fadeIn {
0% {
opacity: 0;
top: 55%;
}
100% {
opacity: 1;
top: 48%;
}
}
@-o-keyframes fadeIn {
0% {
opacity: 0;
top: 55%;
}
100% {
opacity: 1;
top: 48%;
}
}
@keyframes fadeIn {
0% {
opacity: 0;
top: 55%;
}
100% {
opacity: 1;
top: 48%;
}
}
@media only screen and (max-width: 479px) {
.slick-initialized .item p, .slick-initialized .item span, .slick-initialized .item .add, .slick-initialized .item .minus, .checkout .cross, .checkout .slick-initialized .cart .total {
font-size: 1.3em;
}
#app {
width: 100vw;
height: 91vh;
left: 0;
transform: translateX(0%) translateY(0%);
border-radius: 0;
}
#app .board {
background-size: 110% 110%;
background-position: 55% 55%;
}
#app .board .items {
height: 65vh;
}
#app .board .items .item {
padding-top: 1.3em;
}
#app .board .items .item .img {
width: 77%;
height: 46vh;
margin: auto;
}
#app .board nav {
margin: 0em 3.2em;
padding-top: 2.3em;
}
#app .checkout {
min-height: 400px;
}
#app .checkout .boxes .details .card {
width: 80%;
height: 22vh;
font-size: 0.8em;
}
#app .checkout .boxes .details form .item {
width: 75%;
}
#app .checkout .boxes .details form .item input {
width: 100%;
margin: 0;
}
#app .checkout .boxes .details form .submit {
width: 65%;
padding: 0.3em;
}
#app .checkout .boxes .cart .shipping {
width: 50%;
}
#app .checkout .boxes .cart ul li .img {
width: 30%;
}
}
Step 3 (JavaScript Code):
Finally, we need to create a function in JavaScript.
Let's break it down step by step:
- 1. Item Data Array: It initializes an array called item_data containing objects representing items in the supermarket. Each object contains properties such as URL for the item image, name, price, quantity bought (bought), and a boolean value to determine whether to show the item (show).
2. Vue Instance Creation: It creates a new Vue instance app with the following options:
- el: Specifies the HTML element with the id #app where Vue will be mounted.
- data: Contains the initial data for the Vue instance, including the supermarket title, item data array, card details, and shipping cost.
- methods: Defines custom methods to handle events like closing the checkout modal, showing items, adding and removing items from the cart, and slick slider functionality.
- computed: Computes and returns the total cost of all items in the cart including shipping.
3. jQuery Document Ready Function: It waits for the document to be ready before executing the following functions:
- Initializes a slick slider for the .items class, which presumably represents the carousel for displaying items.
- Hides the checkout section initially.
Create a JavaScript file with the name script.js and paste the given codes into your JavaScript file and make sure it's linked properly to your HTML document so that the scripts are executed on the page. Remember, you’ve to create a file with .js extension.
var item_data=[
{url:"https://s6.postimg.cc/w2i224phd/almonds_1740176_1920.png",
name:"堅果",
price: 20,
bought: 0,
show: false
},{url:"https://s6.postimg.cc/7n9u12qkh/bread_1915886_1920.png",
name:"麵包",
price: 30,
bought: 0,
show: false
},
{url:"https://s6.postimg.cc/8mwglse81/federal-carrots-1083235_1920.png",
name:"紅蘿蔔",
price: 30,
bought: 0,
show: false
},
{url:"https://s6.postimg.cc/psmsf4q2p/dish_1883501_1920.png",
name:"水果",
price: 30,
bought: 0,
show: false
},
{url:"https://s6.postimg.cc/wkd7hzf29/egg_1505021_1920.png",
name:"蛋",
price: 30,
bought: 0,
show: false
},
{url:"https://s6.postimg.cc/hfdf9gzcx/meet-1154341_1920.png",
name:"肉",
price: 30,
bought: 0,
show: false
}
];
var app=new Vue({
el:"#app",
data:{
title:"SuperMarket",
items:item_data,
card:{
card_number:"",
card_holder:"",
expires:"",
ccv:""
},
shipping: $('.stuff li').length>=0?200:0
},
methods:{
close: function(){ $('.board').css('filter','blur(0em)')
$('.fa-shopping-cart').css('display','inline');
$('.checkout').hide();
},
show: function(callback){
$('.board').css('filter','blur(0.1em)');
$('.fa-shopping-cart').css('display','none');
$('.checkout').show();
callback && callback();
},
minus: function(index){
var item=this.$data.items[index];
if(item.bought>1){
item.bought-=1;
}else if(item.bought==1){
item.bought-=1;
item.show=false;
}else{
item.bought==0;
}},
plus: function(index){
var item=this.$data.items[index];
item.bought+=1;
item.show=true;
},
neaten_slick: function(){
$('.slick-disabled').trigger('click');
}
}
,
computed:{
total: function(){
var array=this.$data.items,
length=array.length,
shipping=this.$data.shipping,
sum=shipping;
for(i=0;i<length;i++){
sum+=
array[i].price*array[i].bought;
}
return sum;
}
}
}
);
$(document).ready(function(){
$('.items').slick({
dots: true,
infinite: true,
speed: 300,
slidesToShow: 1,
adaptiveHeight: true
});
$('.boxes').slick({
dots: true,
infinite: false,
speed: 100,
slidesToShow: 1,
});
$('.checkout').hide();
});
Final Output:
Conclusion:
Building a shopping cart with HTML, CSS, Vue.js, and Slick.js is a straightforward process. By following this guide, you’ve learned how to set up a Vue project, create a responsive design, and integrate a carousel for product images. This approach not only enhances the user experience but also showcases the power of combining modern web technologies.
Code by: Yumi Chen
That’s a wrap!
I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.
Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee
And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!
Thanks!
Faraz 😊