DEV Community

Cover image for How to make a QR Code generator using JavaScript?
Murtuzaali Surti
Murtuzaali Surti

Posted on • Edited on

How to make a QR Code generator using JavaScript?

While you can generate QR codes for URLs in browsers such as Chrome, it's always interesting to learn how you can make your own version of a simple QR code generator. So, here we go.

HTML

Here's a quick look at the HTML code and it's pretty straightforward.




<section class="heading">
    <div class="title">QRcodes</div>
    <div class="sub-title">Generate QRCode for anything!</div>
</section>
<section class="user-input">
    <label for="input_text">Type something...</label>
    <input type="text" name="input_text" id="input_text" autocomplete="off">
    <button class="button" type="submit">Generate QR Code</button>
</section>
<div class="qr-code" style="display: none;"></div>
<script src="./js/app.js"></script>



Enter fullscreen mode Exit fullscreen mode

The last element is for the QR code to be displayed as soon as we fetch it from a library through javascript (more on that later).

Let's move on to some javascript.

JavaScript

First of all, we will create an event for when the user clicks on the Generate QR code button.




let btn = document.querySelector(".button");
btn.addEventListener("click", () => {
   //code
})



Enter fullscreen mode Exit fullscreen mode

Now, we are going to create a function known as generate() which will be invoked as soon as the user clicks on the Generate QR code button. This function will take the text input from the user as a parameter.




function generate(user_input) {
    //code
} 



Enter fullscreen mode Exit fullscreen mode

Inside this function, we are going to use a javascript library qrcode.js to generate QR code. You can use this library via a CDN by including the below <script> tag in the <head> tag of html.




<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>



Enter fullscreen mode Exit fullscreen mode

Inside the generate() function, we will create a new object using the given library. It will take two arguments, first is the element in which the QR code has to be displayed and secondly, the content for which the QR code has to be generated and some options to customize the QR code.




function generate(user_input) {
    var qrcode = new QRCode(document.querySelector(".qr-code"), {
        text: `${user_input.value}`,
        width: 180, //default 128
        height: 180,
        colorDark : "#000000",
        colorLight : "#ffffff",
        correctLevel : QRCode.CorrectLevel.H
    });
} 



Enter fullscreen mode Exit fullscreen mode

Next, we will create a download button and append it below the QR code.




let download = document.createElement("button");
document.querySelector(".qr-code").appendChild(download);



Enter fullscreen mode Exit fullscreen mode

Inside this download button we will add a link which allows users to download the QR code with a specified file name and append it into the download button. You can learn more about the download attribute here.




let download_link = document.createElement("a");
download_link.setAttribute("download", "qr_code_linq.png");
download_link.innerText = "Download";
download.appendChild(download_link);



Enter fullscreen mode Exit fullscreen mode

Let's figure out the href attribute of the <a> tag next.

The qrcode object will return a canvas element as well as an image element.

For smartphones, the canvas element will be visible but for desktop, the image element will be visible having a src attribute set to a dataURL. We will use the dataURL to download the QR code.

In the case of desktop, it's pretty obvious. We just have to grab the value of src attribute of the image element and assign it to the href attribute of the download link (<a> tag) after a specified amount of time (0.3 seconds) using setTimeout() function because the QR code takes some time to be generated.




let qr_code_img = document.querySelector(".qr-code img");
setTimeout(() => {
    download_link.setAttribute("href", `${qr_code_img.getAttribute("src")}`);
}, 300);



Enter fullscreen mode Exit fullscreen mode

But how do we get the dataURL from the canvas element? By using the method toDataURL() on the canvas element.




let qr_code_canvas = document.querySelector("canvas");
setTimeout(() => {
    download_link.setAttribute("href", `${qr_code_canvas.toDataURL()}`);
}, 300);



Enter fullscreen mode Exit fullscreen mode

After applying some logic, we get this:




if(qr_code_img.getAttribute("src") == null){
    setTimeout(() => {
        download_link.setAttribute("href", `${qr_code_canvas.toDataURL()}`);
    }, 300);
} else {
    setTimeout(() => {
        download_link.setAttribute("href", `${qr_code_img.getAttribute("src")}`);
    }, 300);
}



Enter fullscreen mode Exit fullscreen mode

Also, the .qr-code element will be hidden until the user clicks on the Generate QR code button. With this, our generate() function is all set to be invoked.




function generate(user_input){

    document.querySelector(".qr-code").style = "";

    var qrcode = new QRCode(document.querySelector(".qr-code"), {
        text: `${user_input.value}`,
        width: 180, //128
        height: 180,
        colorDark : "#000000",
        colorLight : "#ffffff",
        correctLevel : QRCode.CorrectLevel.H
    });

    console.log(qrcode);

    let download = document.createElement("button");
    document.querySelector(".qr-code").appendChild(download);

    let download_link = document.createElement("a");
    download_link.setAttribute("download", "qr_code_linq.png");
    download_link.innerText = "Download";

    download.appendChild(download_link);

    if(document.querySelector(".qr-code img").getAttribute("src") == null){
        setTimeout(() => {
            download_link.setAttribute("href", `${document.querySelector("canvas").toDataURL()}`);
        }, 300);
    } else {
        setTimeout(() => {
            download_link.setAttribute("href", `${document.querySelector(".qr-code img").getAttribute("src")}`);
        }, 300);
    }
}



Enter fullscreen mode Exit fullscreen mode

Now inside our click event function, we will check if there is already a QR code displayed or not. If it is, then we will first clear that QR code and generate a new one. If it's not present, we can simply generate a new one.

Also, all of this happens only if the user enters some text or if the input value is not empty.




btn.addEventListener("click", () => {
    let user_input = document.querySelector("#input_text");
    if(user_input.value != "") {
        if(document.querySelector(".qr-code").childElementCount == 0){
            generate(user_input);
        } else{
            document.querySelector(".qr-code").innerHTML = "";
            generate(user_input);
        }
    } else {
        document.querySelector(".qr-code").style = "display: none";
        console.log("not valid input");
    }
})



Enter fullscreen mode Exit fullscreen mode

You can style the elements the way as you want. Here are the styles that I went for:




:root{
    font-size: 62.5%;
}
*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    text-size-adjust: none;
    -webkit-text-size-adjust: none;
}
button:hover{
    cursor: pointer;
}

body{
    display: flex;
    flex-direction: column;
    align-items: center;
    background-color: #EAE6E5;
}
.heading{
    margin: 3rem 0 5rem 0;
}
.title, .sub-title{
    font-size: 4rem;
    text-align: center;
    font-family: 'Poppins', sans-serif;
    color: #12130F;
}
.sub-title{
    font-size: 1.5rem;
    color: #8F8073;
}

.user-input{
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
}
.user-input label{
    text-align: center;
    font-size: 1.5rem;
    font-family: 'Poppins', sans-serif;
}
.user-input input{
    width: 80%;
    max-width: 35rem;
    font-family: 'Poppins', sans-serif;
    outline: none;
    border: none;
    border-radius: 0.5rem;
    background-color: #9b8774ad;
    text-align: center;
    padding: 0.7rem 1rem;
    margin: 1rem 1rem 2rem 1rem;
}
.button{
    outline: none;
    border: none;
    border-radius: 0.5rem;
    padding: 0.7rem 1rem;
    margin-bottom: 3rem;
    background-color: #5b92799d;
    color: #12130F;
    font-family: 'Poppins', sans-serif;
}

.qr-code{
    border-top: 0.5rem solid #8F8073;
    border-right: 0.5rem solid #8F8073;
    border-bottom: 1rem solid #8F8073;
    border-radius: 0.5rem;
    border-bottom-left-radius: 0.5rem;
    border-bottom-right-radius: 0.5rem;
    border-left: 0.5rem solid #8F8073;
    background-color: #8F8073;
}
.qr-code button{
    display: flex;
    justify-content: center;
    background-color: #8F8073;
    font-family: 'Poppins', sans-serif;
    color: #EAE6E5;
    border: none;
    outline: none;
    width: 100%; 
    height: 100%; 
    margin-top: 1rem;
}
.qr-code button a{
    width: 100%;
    height: 100%;
    text-decoration: none;
    color: #EAE6E5;
}



Enter fullscreen mode Exit fullscreen mode

Here is a demo of the entire project:

Here's the github repository for this project.

GitHub logo murtuzaalisurti / qr

A QR Code Generator and Reader! Generate as well as scan QR codes real quick!

That's all for now. I am on Twitter as well as GitHub.

Top comments (29)

Collapse
 
activenode profile image
David Lorenz

Thank you for the article. It shows how to generate a QR Code which can be helpful. However I suggest you change the title toCreating a QR Code with JavaScript because the term Vanilla JS refers to using pure JavaScript. When I read the title I clicked the article because I thought you were actually showing it with Vanilla JS but instead you are using a library which is not Vanilla JS. Try to imagine this: I tell someone "How to get a DOM Element with VanillaJS" and then I show how to load jQuery to then query with jQuery the DOM Element.

Again: The article in itself is helpful but the title very misleading.

Collapse
 
jonrandy profile image
Jon Randy 🎖️ • Edited

A number of issues here....

You're using a submit button without a form. Adding a form would actually be better too, as you could generate the QR code by also pressing return to submit the form. This is standard, expected behaviour on a form.

You're repeatedly calling document.querySelector to get the same things. Would be better just to call it once.

If you have an element with an id - you don't need to use document.querySelector('#id') at all - the element will already be available as window.id, or just id.

Putting all of this together, you can simplify your code considerably.

Also, this isn't really a QR code generator at all - it's an interface to call a 3rd party function that generates a QR code. You should try writing such a generator yourself - it's quite interesting, and you find out how QR codes work.

Collapse
 
activenode profile image
David Lorenz

I agree to everything but the ID approach. Using global definitions is not recommended as there is technically no guarantee it's gonna be the DOM Element (stackoverflow.com/a/18713391/1236627).

Collapse
 
jonrandy profile image
Jon Randy 🎖️

In simple code like your example, you can guarantee it

Thread Thread
 
activenode profile image
David Lorenz • Edited

Context-free, yes. But that wasn't my point. The point is that it is generally not recommended besides for e.g. CodePens or Debugging sessions so I recommend to be careful with that advice. (Or in other words: Even in a large-scale enterprise application I could state "but here it is working" - which then only holds true as long as the overall context (switching libraries, new employees adding new code, etc) does not change. Which is not a good idea.)

Thread Thread
 
jonrandy profile image
Jon Randy 🎖️

Yup - agree. It's appropriate to use in the right context. It should never be avoided just because people "don't understand it" or "aren't used to doing it that way" - way too much of that goes on these days

Thread Thread
 
activenode profile image
David Lorenz • Edited

The problem is that this is viewed from a "small context perspective". In production, as stated, it shouldn't be recommended to be used.

It goes the same principle as always e.g. Security through Obfuscation is definitely working in the right context. But it's recommended to be avoided at all costs in programming because it opens up an option to be breached.

And the similiar goes for window[[id] . If being used in non-prod envs such as showing something or Sandboxes then it can be very helpful (this is where I actually do use it).

But for prod it should be avoided as a guideline. Generally in JS we try to modularize more to enable teams to scale and be free from dependencies from other teams.

Now imagine one team has the idea of using window[id] for their component that they are building. And say both teams are using e.g. a submitButton which is very likely. Now because they allowed themselves to do so they would be allowed to add id="submitButton" . So not only now the ID is double-placed but also the window[id] is ambigious. So the teams are suddenly very dependent on each other, communication effort increases, etc.

On top of that comes another problem: You are polluting the global context. Libraries are polluting the global context too - because they have to. E.g. analytics libraries might expose const analytics = whatever in the window scope. That happens in enterprise applications extremely often because the 3d-party tracking tool needs access to it. The const analytics now takes precedence over any DOM ID definition. So now the approach of using window[domId] wouldn't work anymore.

In any prod-bound or team-bound contexts where more than 1 person works or anything is supposed to scale in the future this should definitely not be used.

Thread Thread
 
lionelrowe profile image
lionel-rowe • Edited

From the HTML spec:

window[name]: As a general rule, relying on this will lead to brittle code. Which IDs end up mapping to this API can vary over time, as new features are added to the web platform, for example. Instead of this, use document.getElementById() or document.querySelector().

The only reason this feature hasn't been removed is that (as with many other bizarre features of the early Web) it can't be changed without breaking legacy code. It's the same reason you can write <body bgcolor="butts"> and get a handsome brick-red background for your page.

Collapse
 
murtuzaalisurti profile image
Murtuzaali Surti

Yup I agree that I used a JS library but this is actually a beginner friendly tutorial to make a QR code generator web app on your own.

Collapse
 
kritikgarg profile image
kritikgarg

🙌 Thanks for sharing this amazing article, Murtuzaali! 🤓

I found the step-by-step instructions on how to create a QR code generator using JavaScript to be super helpful. 🤩

I've been wanting to learn more about QR codes and how they can be used in Salesforce, so your article was timely. 🤑

I also recently read the article on How to Use QR Codes in Salesforce and found it to be a great complement to your article. 🤞

Both pieces of content provided valuable insights on the potential uses and benefits of QR codes in Salesforce. 💪

Keep up the great work!

Collapse
 
murtuzaalisurti profile image
Murtuzaali Surti

Thank You!

Collapse
 
lexlohr profile image
Alex Lohr

There's a Barcode Detection API in modern browsers. You'd only need to polyfill it if it is not supported.

Collapse
 
activenode profile image
David Lorenz

Which is helping for Detection, not for creation. But thanks for the hint 👍

Collapse
 
murtuzaalisurti profile image
Murtuzaali Surti • Edited

It's not available for all browsers. Thanks for suggesting, I didn't knew about this earlier!

Collapse
 
thenickest profile image
TheNickest

Interesting article but the title is misleading. Neither vanilla flavour nor generating anything

Collapse
 
murtuzaalisurti profile image
Murtuzaali Surti

This is an article which appeals to beginners!

Collapse
 
thenickest profile image
TheNickest

Does not mean that the title should be misleading!

Thread Thread
 
murtuzaalisurti profile image
Murtuzaali Surti

changed

Collapse
 
techtitans0101 profile image
TechTitans0101 • Edited

Open source is essential for application developers. It is unfortunate that Open Base is shutting down. If you are looking for an alternative, check out kandi from Open Weaver. kandi helps developers build applications faster through open source reuse. Through its natural language interface, kandi recommends code snippets, packages, libraries and solutions from 650 Million open source assets. kandi also promotes responsible reuse with proper license attribution across all assets, while guiding the developer on paring code snippets with libraries to build their applications faster.

Try kandi at kandi.openweaver.com. Thank you for your support to the open source community and happy coding!

Collapse
 
anubhavshakya profile image
Anubhav Shakya

Hey guys,
Is there any library for react-native ??? I need to design stylish qr code.

Collapse
 
murtuzaalisurti profile image
Murtuzaali Surti
Collapse
 
techtitans0101 profile image
TechTitans0101 • Edited

Open source is essential for application developers. It is unfortunate that Open Base is shutting down. If you are looking for an alternative, check out kandi from Open Weaver. kandi helps developers build applications faster through open source reuse. Through its natural language interface, kandi recommends code snippets, packages, libraries and solutions from 650 Million open source assets. kandi also promotes responsible reuse with proper license attribution across all assets, while guiding the developer on paring code snippets with libraries to build their applications faster.

Try kandi at kandi.openweaver.com. Thank you for your support to the open source community and happy coding!

Collapse
 
anubhavshakya profile image
Anubhav Shakya

Thanks, I will explore it.

Collapse
 
umairshah143 profile image
Umair Shah

Build Full QR Code Generator Website using JavaScript
QR Code Generator of Link, Text, Phone, Vcard, Message, App Links
Copy QR Code Image to Clipboard
Download QR Code Image
Change QR Code Size and Color
demo tutorial and source code: bit.ly/3OZcxBH

Collapse
 
blaze_droid profile image
Vikas Dongre

You can't call it vanilla, because you are using an library. I think pure vanilla javascript qr code is not even possible.

Collapse
 
murtuzaalisurti profile image
Murtuzaali Surti

changed on demand

Collapse
 
mzaini30 profile image
Zen

Why setTimeout? Why not async/await?

Collapse
 
murtuzaalisurti profile image
Murtuzaali Surti

Because we don't return any promises which can be resolved!