diff --git a/app/controllers/resources/resource.php b/app/controllers/resources/resource.php
index f152f8efdde8980d93f570570b4cfa4e9e30abcc..d5bb7ac1c97d1f2806033426a779a7ed0e8f6599 100644
--- a/app/controllers/resources/resource.php
+++ b/app/controllers/resources/resource.php
@@ -565,7 +565,7 @@ class Resources_ResourceController extends AuthenticatedController
             $actions->addLink(
                 _('QR-Code anzeigen'),
                 $this->resource->getActionURL('booking_plan'),
-                Icon::create('download'),
+                Icon::create('code-qr'),
                 [
                     'data-qr-code' => '',
                     'data-qr-code-print' => '1'
diff --git a/app/controllers/resources/room_planning.php b/app/controllers/resources/room_planning.php
index 23056bc5ab4953722ef64d70d09f84530be13c0b..c4bf84aac6be8fbcc15060071818196a04c83d8c 100644
--- a/app/controllers/resources/room_planning.php
+++ b/app/controllers/resources/room_planning.php
@@ -355,7 +355,7 @@ class Resources_RoomPlanningController extends AuthenticatedController
             $actions->addLink(
                 _('QR-Code anzeigen'),
                 $this->resource->getActionURL('booking_plan'),
-                Icon::create('download'),
+                Icon::create('code-qr'),
                 [
                     'data-qr-code'       => '',
                     'data-qr-code-print' => '1',
diff --git a/package-lock.json b/package-lock.json
index 1e6fdfedc846c2b28f0656ccf10ac00bd925f4bc..1c7688790cddaa303b2975b4c464990874c85eef 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -49,6 +49,7 @@
                 "jquery-ui": "1.13",
                 "jquery-ui-timepicker-addon": "1.6.3",
                 "jquery-ui-touch-punch": "0.2.3",
+                "jquery.qrcode": "^1.0.3",
                 "jquery.scrollto": "2.1.2",
                 "jspdf-yworks": "^2.1.1",
                 "jszip": "^3.6.0",
@@ -7652,6 +7653,12 @@
             "integrity": "sha1-7tgiQnM7okP0az6HwYQbMIGR2mg=",
             "dev": true
         },
+        "node_modules/jquery.qrcode": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/jquery.qrcode/-/jquery.qrcode-1.0.3.tgz",
+            "integrity": "sha1-mK003rf0AdcpgcZ2l5DL04qqOfA=",
+            "dev": true
+        },
         "node_modules/jquery.scrollto": {
             "version": "2.1.2",
             "resolved": "https://registry.npmjs.org/jquery.scrollto/-/jquery.scrollto-2.1.2.tgz",
@@ -20852,6 +20859,12 @@
             "integrity": "sha1-7tgiQnM7okP0az6HwYQbMIGR2mg=",
             "dev": true
         },
+        "jquery.qrcode": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/jquery.qrcode/-/jquery.qrcode-1.0.3.tgz",
+            "integrity": "sha1-mK003rf0AdcpgcZ2l5DL04qqOfA=",
+            "dev": true
+        },
         "jquery.scrollto": {
             "version": "2.1.2",
             "resolved": "https://registry.npmjs.org/jquery.scrollto/-/jquery.scrollto-2.1.2.tgz",
diff --git a/package.json b/package.json
index 10483762d77f8d54612b9155d4f6c7753174df29..ab28535262e6e0825d71de06f291946213cb05f1 100644
--- a/package.json
+++ b/package.json
@@ -60,6 +60,7 @@
         "jquery-ui": "1.13",
         "jquery-ui-timepicker-addon": "1.6.3",
         "jquery-ui-touch-punch": "0.2.3",
+        "jquery.qrcode": "^1.0.3",
         "jquery.scrollto": "2.1.2",
         "jspdf-yworks": "^2.1.1",
         "jszip": "^3.6.0",
diff --git a/resources/assets/javascripts/bootstrap/qr_code.js b/resources/assets/javascripts/bootstrap/qr_code.js
index cddc1533dde19bfe4c10440de775fa9806384bf2..3a627f7e2906e2a16e269a555490a814ce173274 100644
--- a/resources/assets/javascripts/bootstrap/qr_code.js
+++ b/resources/assets/javascripts/bootstrap/qr_code.js
@@ -1,4 +1,4 @@
-jQuery(document).on('click', 'a[data-qr-code]', function (event) {
+$(document).on('click', 'a[data-qr-code]', function (event) {
     const data = $(this).data();
     STUDIP.QRCode.show(this.href, {
         print: data.qrCodePrint ?? false,
@@ -8,43 +8,3 @@ jQuery(document).on('click', 'a[data-qr-code]', function (event) {
 
     event.preventDefault();
 });
-
-STUDIP.ready((event) => {
-    $('code.qr', event.target).each(function () {
-        let content = $(this).text().trim();
-        let code    = $('<div class="qrcode">').hide();
-        STUDIP.QRCode.generate(code[0], content, {
-            width: 1024,
-            height: 1024
-        });
-        $(this).replaceWith(code);
-        setTimeout(() => code.show(), 0);
-    });
-    jQuery(document).on(
-        'click',
-        '#qr_code .PrintAction',
-        function() {
-            //We must hide the other page elements for the print view functionality.
-            //Furthermore we must set the width and height of the qr-code.
-            jQuery('#layout_wrapper').css(
-                {
-                    display: 'none'
-                }
-            );
-            jQuery('#qr_code').addClass('print-view');
-
-            //Now we can print:
-            window.print();
-        }
-    );
-
-    jQuery(document).on(
-        'fullscreenchange webkitfullscreenchange mozfullscreenchange MSFullscreenChange',
-        function(event) {
-            //After the print action is called
-            //we must reset the style changes made above:
-            jQuery('#layout_wrapper').removeAttr('style');
-        }
-    );
-});
-
diff --git a/resources/assets/javascripts/jquery-bundle.js b/resources/assets/javascripts/jquery-bundle.js
index 51e3b550b6887fb98b61ab74a45df72e2558a40c..e3724de180d6a2e205d7f6738c1845ca22ce752a 100644
--- a/resources/assets/javascripts/jquery-bundle.js
+++ b/resources/assets/javascripts/jquery-bundle.js
@@ -61,6 +61,7 @@ import 'jquery-ui-timepicker-addon';
 import 'multiselect';
 
 import 'jquery.scrollto';
+import 'jquery.qrcode';
 
 import 'jquery-ui-touch-punch';
 
diff --git a/resources/assets/javascripts/lib/qr_code.js b/resources/assets/javascripts/lib/qr_code.js
index 914db9b6d0a7ee3f940b0b71bfc848ece3e2aefa..3db4fd8703c226fb82657f3007ce31552daccd01 100644
--- a/resources/assets/javascripts/lib/qr_code.js
+++ b/resources/assets/javascripts/lib/qr_code.js
@@ -1,4 +1,3 @@
-import QRCodeGenerator from "../vendor/qrcode-04f46c6.js"
 import { $gettext } from "./gettext.js";
 import Dialog from "./dialog.js";
 
@@ -28,7 +27,7 @@ const QRCode = {
         }
 
         // Actually generate code
-        new QRCodeGenerator(code[0], {
+        code.qrcode({
             text: text,
             width: 1280,
             height: 1280,
@@ -69,6 +68,12 @@ const QRCode = {
                     click () {
                         var openWindow = window.open("", '_blank');
                         openWindow.document.write(`<body style="text-align: center;">${content.html()}</body>`);
+                        // Copy qrcode canvas itself (as it is not included in .html()
+                        openWindow.document.querySelector('canvas').getContext('2d').drawImage(
+                            $('canvas', code)[0],
+                            0,
+                            0
+                        );
                         openWindow.document.close();
                         openWindow.focus();
                         openWindow.print();
@@ -78,20 +83,11 @@ const QRCode = {
             }, buttons);
         }
 
-
         Dialog.show(content, {
             title: options.title ?? $gettext('QR-Code'),
             size: 'big',
             buttons
         });
-    },
-    generate: function (element, text, options = {}) {
-        options.text = text;
-        if (options.correctLevel === undefined) {
-            options.correctLevel = 3;
-        }
-
-        var qrcode = new QRCodeGenerator(element, options);
     }
 };
 
diff --git a/resources/assets/stylesheets/less/qrcode.less b/resources/assets/stylesheets/scss/qrcode.scss
similarity index 91%
rename from resources/assets/stylesheets/less/qrcode.less
rename to resources/assets/stylesheets/scss/qrcode.scss
index 4f9773da351f16856263e1c99215d303ee9a3dd5..c6a8747615d0139ea3ca2490daf3bc88f2cdcbf9 100644
--- a/resources/assets/stylesheets/less/qrcode.less
+++ b/resources/assets/stylesheets/scss/qrcode.scss
@@ -14,8 +14,9 @@
         flex: 0 1 auto;
         max-height: 90%; // TODO This will not scale well if description grows
         width: 100%;
+        text-align: center;
 
-        img {
+        canvas {
             margin: auto;
             max-height: 100%;
             object-fit: contain;
@@ -26,6 +27,7 @@
     .description {
         flex: 0 0 auto;
         margin-top: 1em;
+        text-align: center;
     }
 
     &:fullscreen {
diff --git a/resources/assets/stylesheets/studip.less b/resources/assets/stylesheets/studip.less
index 99fe302bc3ad4c0d0eb9d373a2bd7b37792767e3..07550d49205ddd729a80ee093c480d1e0ddcb67e 100644
--- a/resources/assets/stylesheets/studip.less
+++ b/resources/assets/stylesheets/studip.less
@@ -41,7 +41,6 @@
 @import "less/skiplinks.less";
 @import "less/tabs.less";
 @import "less/questionnaire.less";
-@import "less/qrcode.less";
 @import "less/copyable-links.less";
 
 @import "less/admin.less";
diff --git a/resources/assets/stylesheets/studip.scss b/resources/assets/stylesheets/studip.scss
index 3241caa7d542b3b660bb9d4dbf5f6ba92b7e67e6..ed867ef91087cc68b4e935c8348608ac23138e58 100644
--- a/resources/assets/stylesheets/studip.scss
+++ b/resources/assets/stylesheets/studip.scss
@@ -23,6 +23,7 @@
 @import "scss/progress_indicator.scss";
 @import "scss/my_courses";
 @import "scss/oer";
+@import "scss/qrcode";
 @import "scss/report";
 @import "scss/resources";
 @import "scss/sidebar";