Nowadays more and more people are using Android and iOS devices to access websites more than they use their desktop devices. So, the mobile-first design is recently coming to our attention a lot. But one thing got me thinking, if we can create websites keeping smaller handheld devices in mind, then we should use some mobile-specific features to give the users some cool experience.
In most of the websites, I have seen that a hamburger menu is implemented to hide the navigations and save some space. But they just provide a button to click to open up the hamburger menu. That just does not feel good to me. It was also the same case on my website as well. Recently I implemented a swipe action that can open and close the menu, which feels more natural thing to do in a mobile, touchscreen device. And it looks like this:
Is not it cool? The circle shows the touch position and on touch, it disappears.
Most of you who follow me know that I love to make tutorials, and you won't be let down in this post as well, as we will be implementing a todo card where swiping will reveal the delete button for that card. So without further adieu let's jump right into coding.
But before starting if you want to check out this code this will be available on github or glitch. and the hosted version of this will be available here. You should really go and check out the hosted version from your phone to just get the feel. Here is a gif to show this swipe open working:
The folder setup
There is no fancy setup required for this project, you will just need an HTML file a CSS file and a JavaScript file all linked up to the HTML file and put into one folder. And obviously you should use a code editor to code rapidly.
Writing up the initial HTML
So, our app doesn't need any fancy HTML layout to do stuff. It will be very simple with a div
of class container
wrapping everything. Inside that div, there will be a div
with a class of card
and inside that div
we will have an h3
with a class of todo_essentials
which will be having our todo text, just to keep the code simple. You can make this todo_essentials
a div
and make this layout complicated.
After that, we need to get that delete button its own space in a button
with the class of delete
, inside which we will be putting a button with a delete icon. I have used a material design icon here. To place this icon we need to import the material design icons:
<link
rel="stylesheet"
href="https://cdn.materialdesignicons.com/5.0.45/css/materialdesignicons.min.css"
/>
Then we have to use a span with class mdi
and mdi-trash-can-outline
to make the icon.
So now our HTML file looks something like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=no"
/>
<title>Swipe Open Controls</title>
<link rel="stylesheet" href="./style.css" />
<link
rel="stylesheet"
href="https://cdn.materialdesignicons.com/5.0.45/css/materialdesignicons.min.css"
/>
</head>
<body>
<div class="container">
<div class="card">
<h3 class="todo_essentials">
Todo 001
</h3>
<button class="delete_button">
<span class="mdi mdi-trash-can-outline"></span>
</button>
</div>
</div>
<script src="./app.js"></script>
</body>
</html>
Now let's just make the site beautiful.
CSS
As this is not a CSS tutorial so we won't be focusing much on the CSS and just will be focusing on the required stuff:
So at first we will be resetting the margin and padding. And then we will be setting the positions using the .container
, the fonts, shadows, font size, margins and padding:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: Arial, Helvetica, sans-serif;
}
body {
background-color: #e9e9e9;
}
.container {
min-width: 100vw;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.card {
width: 80%;
/* border: 2px solid black; */
display: flex;
box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.5);
background-color: aliceblue;
}
.todo_essentials {
padding: 10px 20px;
}
.delete_button {
margin-left: auto;
display: block;
height: match-parent;
padding: 5px 20px;
background-color: #da0d25;
color: white;
outline: none;
border: none;
font-size: 1.3rem;
}
Now this will be the time to discuss how this sliding mechanism works. So, here I simply set the the transform-origin
to the right(as our button is on the right side of the screen) then set the scaleX
to 0 using the transform
property. Then I set a few animations and set the cursor to a pointer, for desktop view.
.delete-button{
/* rest of the stuff */
transform-origin: right;
transform: scaleX(0);
transition: transform 0.3s ease-in-out, background-color 0.3s ease-in-out;
cursor: pointer;
}
Talking about desktop views, here are some settings I used to show the delete button on hover for desktops:
.delete_button:hover,
.delete_button:focus {
background-color: #9c0315;
}
@media only screen and (min-width: 600px) {
.container {
min-width: 0;
max-width: 500px;
margin: 0 auto;
}
}
@media only screen and (min-width: 900px) {
.card:hover .delete_button {
transform: scaleX(1) !important;
}
}
Next, we will be jumping into the meat of the project i.e the JavaScript stuff. But before that, let me tell about the available touch events and how we will be using them.
The touch events available in the browsers
There are mainly four touch events for which you can listen to:
1. touchstart: This detects the start of touch/touches and fires eventlistener. If you see the event object available in the callback to eventlistener, we get a list of touches, each one containing some x and y co-ordinates with respect to the screen, window, page and etc. The object for a touch looks something like this:
{
identifier: 0
target: div.card
screenX: 2661
screenY: 471
clientX: 273
clientY: 336
pageX: 273
pageY: 336
radiusX: 11.5
radiusY: 11.5
rotationAngle: 0
force: 1
}
2. touchmove: As the event name suggests it fires when one of the started touches is moved.
3. touchend: As the event name suggests it will fire once a touch is ended i.e. your finger is moved out of the screen.
There is also one more touch event there, about which I don't have much knowledge.
4. touchcancel
Each of the above events yields out an object, where according to me the most important things are touches, targetTouches and changedTouches. I am still exploring the touch events and will be exploring and sharing more in future.
With the basics of touch events covered I will now be diving into coding our main swipe, which will be relying on a simple concept: when the touch starts we will note the initial touch x of touch[0]
the user. Then on the move of touch, we will take the x position of touch[0]
and will find the difference between the initial touch x and this touch. And when the touch ends, if the difference of the final position x and initial x is less than 0 then we can say that there was a left swipe, and otherwise, we can say there was a right swipe. The explanation can be found using the diagram below:
So, let's just code the touch handling.
JavaScript
To start things off we will need the reference of the card
and our delete button
. We need the reference to the card to add touch event listeners. Then we need a reference to the button to show and hide it accordingly. We also will need a boolean to store whether the button is shown or not. Then we need a variable to store the initial x position and the movement in x. I also create a constant to create a small threshold to eliminate accidental swipe detection. So far this code will look like this:
const card = document.querySelector(".card");
const theDeleteButton = document.querySelector(".delete_button");
const MOVE_THRESHOLD = 100;
let initialX = 0;
let moveX = 0;
let isDeleteButtonOpen = false;
So, the next thing will be to add event listeners to the card. As told before, on touch start we will get the initial x position of touch in our initialX
variable:
card.addEventListener("touchstart", e => {
initialX = e.touches[0].pageX;
});
Now, at movement we were to get the current position and calculate the movement. This is done so as sometimes the position is not found properly at the end of the touch(at least for me it as not working properly). So the code for touchmove
will look like:
card.addEventListener("touchmove", e => {
let currentX = e.touches[0].pageX;
moveX = currentX - initialX;
});
Now, at the touchend
event we need to check if it was left swipe and or a right swipe by checking if our moveX
amount was less than or greater than the MOVE_THRESHOLD
multiplied by the sign of the moveX
. If our value of moveX
is less than the calculated MOVE_THRESHOLD
then as explained before we can say that the swipe was a left swipe otherwise, if our value of moveX
is greater than the calculated MOVE_THRESHOLD
then we can say it was a right swipe. Then we have the isDeleteButtonOpen
boolean which says whether the button is visible or not.
So, if the swipe was left and the button was not open we set the scaleX
of the button to 1(as by setting scaleX 0 we hid the button) and also set the isDeleteButtonOpen
to true. and if the swipe was right and the button was open we set the scaleX
to 0. At the end don't forget to reset the variable storing the movement, otherwise it may cause wierd behaviour. So the final code for touchend
will be like:
card.addEventListener("touchend", e => {
if (moveX < MOVE_THRESHOLD * Math.sign(moveX) && !isDeleteButtonOpen) {
theDeleteButton.style.transform = "scaleX(1)";
isDeleteButtonOpen = true;
} else if (moveX > MOVE_THRESHOLD * Math.sign(moveX) && isDeleteButtonOpen) {
theDeleteButton.style.transform = "scaleX(0)";
isDeleteButtonOpen = false;
}
moveX = 0;
});
So the final project will be working properly now.
Conclusion
So, this was a simple tutorial for using swiping gestures on a webpage. But you can build a lot on this, like adjusting the x scale according to the movement, or doing something cooler with different swipe gestures - maybe a small game. The creativity is endless. Until my next post stay happy and keep coding. And keeping in the current condition in mind, stay home, stay safe.
Top comments (1)
Thanks for sharing. I found this CSS approach in my research and testing; and the behavior on iOS Chrome and Safari is really good.
Example:
codepen.io/zouhir/embed/RMMvGZ?
Blog, Details:
medium.com/@_zouhir/swipe-views-wi...