Build your own mobile friendly website with Flask.

As a regular python user, I dreamed about building my own webpage with python, because I knew it is possible. Even though there are a lot tutorials of how to build a website with Flask, there are very only few stackoverflow snippets about building a mobile friendly web page. Integrating a responsive navigation bar is the first important step for that. Nowadays it is really necessary to have that, because around 60% of the people are surfing with their smartphones (Link to recent statistics 2021: Here). So if you want an attractive web page, it should be mobile friendly!

In this tutorial I show you how to develop and build the basics for a mobile friendly website. Everything I show you here, I have gathered in the internet, so it is just a collection and step-by-step guide for you.

In a next step and different tutorial I will show you how to deploy your own web page on pythonanywhere.com*, where I also host my website. For this tutorial you should know a little about Python, HTML and CSS.

Requirements

  • Python 3.8+ or Anaconda
  • Integrated Development Environment (IDE)

Development Framework

To develop your webpage from scratch, you need an IDE (Integrated Development Environment). For the IDE I personnally use and recommend PyCharm. It is really easy to use, handy with Version Control (Git), installing and updating libraries and using virtual environments. Of course you can also use any other IDE like Visual Studio Code or Atom. If you have already PyCharm or a similar IDE, you can skip this part.

Download and Install the programm from PyCharm for your dedicated system (Windows, macOS or Linux). The community version is free and really enough for this use case. I am using Windows in this tutorial.

Screenshoot from Pycharm
Screenshoot from Pycharm

Initialize your first project

When sucessfully installed, start PyCharm and go to File > New Project. A window pops up and you can name your project and specify the directory on your computer. I named it “Webpage_Tutorial”. Now you can choose if you want a virtual environment or use an exisiting interpreter. I recommend to set up a new virtual environment with “conda” (Anaconda) or any other virtual environment, because it is much simpler to handle you project with your libraries, scaling it up or deploying it. If you do not have Anaconda, you can also simply download and install it (https://docs.conda.io/projects/conda/en/latest/user-guide/install/index.html).

When you click the “Create” button, PyCharm starts to initalize your project and installs the necessary libraries.

Write your first python file

First you will see an empty root directory in PyCharm and you can create your first python file by right clicking on Webpage_Tutorial folder > New > Python File. Name the python file “run.py”, that is your core file, which will handle all your other files like html and css files. It is your “Backend”, what the user will not see.

Afterwards right click on the empty file and click Create ‘run’ to configure your python file.

Add to the Enviroment variables FLASK_APP=run.py and click OK and save the configuration.

Open your Terminal in the bottom left corner and install Flask.

pip install flask == 1.1.2

Write your first browser app in the run.py:

from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def index():
return "Hello World!"


if __name__ == "__main__":
app.directory='./'
app.run(host='127.0.0.1', port=5000)

Now you are able to click on the right hand side in the top corner, the green run button. In the bottom, it opens the RUN Terminal. You can now click on the link 127.0.0.1:5000 which is your localhost. The browser should open and you should see “Hello World”.

Prepare your folder structure

Insert your main root directory, the folders for your static files like your css and your templates folders, where the html files will be located.

Webpage_Tutorial/

├── static
│ └──css
├── templates
│ └──layouts
└── run.py

Insert your CSS

Download from http://getskeleton.com/ the css template, extract the zip file and copy-paste the two files normalize.css and skeleton.css into your css folder.

Create your first HTML file

In your templates directory, create a new HTML file and name it “main.html”. This file will contain your meta and works as an index for your webpage. The title, meta description, keywords, author and robots specifications are necessary for your Google search. Also your stylesheets are included.

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>This is a tutorial</title>
<meta name="description" content="I present to you a free tutorial for developing a mobile friendly app"/>
<meta name="keywords" content="Tutorial, Mobile, Free"/>
<meta name="author" content="<author>" />
<meta name="copyright" content="<author>" />
<meta name="robots" content="index"/>
<meta name="robots" content="follow"/>
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">


<link rel="stylesheet" href="./static/css/normalize.css"/>
<link rel="stylesheet" href="./static/css/skeleton.css"/>

</head>
<body>
<div class="container">

<div style="clear: both">
&nbsp;

{% block content%}{% endblock %}

</div>

</div>
</body>
</html>

Add also your start view, which you can call “home.html”. Insert in your HTML file a replace holder where you can insert variables dynamically via your python backend: {{greetings}}.

{% extends "layouts/main.html" %}

{% block content%}

</body>

<h5>{{greetings}}</h5>

</body>

{% endblock %}

Change your run.py file, that you render your new home file.

@app.route("/")
def index():
greetings = "Hello World"
return render_template("home.html", greetings=greetings)

Your folder directory should look like this:

Now you can run again your run.py to see if the stylesheets and your greetings are displayed correctly.

Create a responsive navigation bar

Now it will be more complicated with css and javascript. Create an additional css with the name “style.css” in your css path and insert following code:

/* Dropdown content (hidden by default) */
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}

/* Links inside the dropdown */
.dropdown-content a {
float: none;
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: left;
}

/* Add a grey background color to dropdown links on hover */
.dropdown-content a:hover {
background-color: #ddd;
}

/* Show the dropdown menu on hover */
.dropdown:hover .dropdown-content {
display: block;
}

/* Add a black background color to the top navigation */
.topnav {
background-color: #333;
overflow: hidden;
}

/* Style the links inside the navigation bar */
.topnav a {
float: left;
display: block;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
}

/* Add an active class to highlight the current page */
.active {
background-color: grey;
color: white;
}

/* Hide the link that should open and close the topnav on small screens */
.topnav .icon {
display: none;
}

/* Dropdown container - needed to position the dropdown content */
.dropdown {
float: left;
overflow: hidden;
}

/* Style the dropdown button to fit inside the topnav */
.dropdown .dropbtn {
font-size: 17px;
border: none;
outline: none;
color: white;
padding: 14px 16px;
background-color: inherit;
font-family: inherit;
line-height: 30px;
}

/* Style the dropdown content (hidden by default) */
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}

/* Style the links inside the dropdown */
.dropdown-content a {
float: none;
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: left;
}

/* Add a dark background on topnav links and the dropdown button on hover */
.topnav a:hover, .dropdown:hover .dropbtn {
background-color: #555;
color: white;
}

/* Add a grey background to dropdown links on hover */
.dropdown-content a:hover {
background-color: #ddd;
color: black;
}

/* Show the dropdown menu when the user moves the mouse over the dropdown button */
.dropdown:hover .dropdown-content {
display: block;
}

/* When the screen is less than 600 pixels wide, hide all links, except for the first one ("Home"). Show the link that contains should open and close the topnav (.icon) */
@media screen and (max-width: 600px) {
.topnav a:not(:first-child), .dropdown .dropbtn {
display: none;
}
.topnav a.icon {
float: right;
display: block;
}
}

@media screen and (max-width: 600px) {
.topnav.responsive {position: relative;}
.topnav.responsive a.icon {
position: absolute;
right: 0;
top: 0;
}
.topnav.responsive a {
float: none;
display: block;
text-align: left;
}
.topnav.responsive .dropdown {float: none;}
.topnav.responsive .dropdown-content {position: relative;}
.topnav.responsive .dropdown .dropbtn {
display: block;
width: 100%;
text-align: left;
}
}

</style>

Now change your main.html to make the additional CSS file effective. You need for the small icons also a source from cloudflare:

<link rel=”stylesheet” href=”https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> 

Also add a dropdown field for additional HTML pages, but this is only a plcaeholder. I am calling it “Examples” and the dropdown “Example 1”.

<div class="dropdown">
<button class="dropbtn">Examples
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-content">
<a href="/Example1">Example 1</a>
</div>
</div>

Insert also the javascript snippet to control the responsiveness navigation bar.

<script>
function myFunction() {
var x = document.getElementById("myTopnav");
if (x.className === "topnav") {
x.className += " responsive";
} else {
x.className = "topnav";
}
}
</script>

All together it will look like that:

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>This is a tutorial </title>
<meta name="description" content="I present to you a free tutorial for developing a mobile friendly app"/>
<meta name="keywords" content="Tutorial, Mobile, Free"/>
<meta name="author" content="<author>" />
<meta name="copyright" content="<author>" />
<meta name="robots" content="index"/>
<meta name="robots" content="follow"/>
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">


<link rel="stylesheet" href="./static/css/normalize.css"/>
<link rel="stylesheet" href="./static/css/skeleton.css"/>
<link rel="stylesheet" href="./static/css/style.css"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">


</head>
<body>
<div class="container">
<div class="topnav" id="myTopnav">
<a href="/" class="active">Home</a>
<div class="dropdown">
<button class="dropbtn">Examples
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-content">
<a href="/Example1">Example 1 </a>
</div>
</div>
<a href="javascript:void(0);" class="icon" onclick="myFunction()">
<i class="fa fa-bars"></i>
</a>
</div>

<div style="clear: both">
&nbsp;

{% block content%}{% endblock %}

</div>

<script>
function myFunction() {
var x = document.getElementById("myTopnav");
if (x.className === "topnav") {
x.className += " responsive";
} else {
x.className = "topnav";
}
}
</script>

</div>
</body>
</html>

When you made the changes and reload your pages, the result should look like that:

Also you can test if the page will change its design by a different device like a smartphone. In Firefox or Chrome you can enter the developer console with F12 and test the smartphone view. In Firefox, it is a small icon in the right bottom corner (blue arrow). As demonstration your navigation bar is smaller and your subitems can be accessed through the doughnut (red arrow).

If you click the doughnut (red arrow) the navigation item will pop out and show its content:

Congratulations! You have developed a mobile friendly website with flask.

You can see this design also on my website: www.antonioblago.com. Contact me on LinkedIn or email, if you have some improvements or feedback to my method here.

On Github you can fork or download this template (Repository). Please give it a star. Thank you!

I am a data analyst, discovered the unlimited world of coding.