Open In App

Build a Virtual Keyboard using HTML CSS & JavaScript

Last Updated : 17 Nov, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

In this article, we will build a virtual keyboard using HTML, CSS, and JavaScript. A virtual keyboard is a user interface component that allows users to input text by clicking on the keys displayed on the screen. Our keyboard will support standard alphanumeric characters, special characters, and a Caps Lock feature.

Preview of final output: Let us have a look at how the final output will look like.

virtual-keyboard-preview

virtual keyboard

Prerequisites:

Approach:

  • Create an HTML file (index.html) to serve as the main structure for the virtual keyboard.
  • Include a <textarea> element where the typed text will appear.
  • Add a <div> element to represent the virtual keyboard. We’ll generate the keyboard keys dynamically using JavaScript.
  • Create a style.css file to style the virtual keyboard and its keys.
  • Define styles for the keyboard layout, keys, background colors, fonts, and any other visual elements.
  • Customize the appearance to match your design preferences.
  • Create a script.js file to handle the functionality of the virtual keyboard.
  • Dynamically generate the keyboard keys using JavaScript and insert them into the <div> element with the id “keyboard.”
  • Add event listeners to the keys to capture click events.
  • Handle key clicks and update the text in the <textarea> accordingly.
  • Implement the Caps Lock feature to toggle between uppercase and lowercase characters.

Example: Below is the implementation of project

Javascript




// script.js
const Keyboard = {
    elements: {
        main: null,
        keysContainer: null,
        keys: [],
        capsKey: null,
    },
 
    properties: {
        value: "",
        capsLock: false,
        keyboardInputs: null,
        keyLayout: [
            "1",
            "2",
            "3",
            "4",
            "5",
            "6",
            "7",
            "8",
            "9",
            "0",
            "backspace",
            "q",
            "w",
            "e",
            "r",
            "t",
            "y",
            "u",
            "i",
            "o",
            "p",
            "caps",
            "a",
            "s",
            "d",
            "f",
            "g",
            "h",
            "j",
            "k",
            "l",
            "enter",
            "done",
            "z",
            "x",
            "c",
            "v",
            "b",
            "n",
            "m",
            ",",
            ".",
            "?",
            "space",
        ],
    },
 
    init() {
        // create and setup main element
        this.elements.main =
            document.createElement("div");
        this.elements.main.classList
            .add("keyboard", "keyboard--hidden");
        document.body
            .appendChild(this.elements.main);
 
        // create and setup child container component
        this.elements.keysContainer =
            document.createElement("div");
        this.elements.keysContainer
            .classList.add("keyboard__keys");
        this.elements.main
            .appendChild(this.elements.keysContainer);
 
        // create and setup key elements
        this.elements.keysContainer
            .appendChild(this._createKeys());
        this.elements.keys =
            this.elements.keysContainer
                .querySelectorAll(".keyboard__key");
 
        // open keyboard for elements with .use-keyboard-input
        this.properties.keyboardInputs =
            document.querySelectorAll(
                ".use-keyboard-input"
            );
        this.properties
            .keyboardInputs
            .forEach((element) => {
                element.addEventListener("focus", () => {
                    this
                        .open(element.value, (currentValue) => {
                            element.value = currentValue;
                        });
                });
            });
    },
 
    _createIconHTML(icon_name) {
        return `<span class="material-icons">${icon_name}</span>`;
    },
 
    _createKeyBtn(iconName, class1, onclick, class2) {
        this.keyElement =
            document.createElement("button");
 
        // add common attributes and classes
        this.keyElement
            .setAttribute("type", "button");
        this.keyElement
            .classList.add("keyboard__key");
 
        // add specific listeners and classes
        this.keyElement
            .classList.add(class1, class2);
        this.keyElement.innerHTML =
            this._createIconHTML(iconName);
        this.keyElement
            .addEventListener("click", onclick);
    },
 
    _createKeys() {
        const fragment =
            document.createDocumentFragment();
 
        this.properties.keyLayout.forEach((key) => {
            const insertLineBreak =
                ["backspace", "p", "enter", "?"].indexOf(key) !== -1;
 
            switch (key) {
                case "backspace":
                    this._createKeyBtn(
                        "backspace", "keyboard__key--wide",
                        () => {
                            this.properties.value =
                                this.properties.value.slice(0, -1);
                            this._updateValueInTarget();
                        });
                    break;
 
                case "caps":
                    this._createKeyBtn(
                        "keyboard_capslock",
                        "keyboard__key--activatable",
                        () => {
                            this.elements.capsKey
                                .classList
                                .toggle("keyboard__key--active");
                            this._toggleCapsLock();
                        },
                        "keyboard__key--wide"
                    );
                    this.elements.capsKey = this.keyElement;
                    break;
 
                case "enter":
                    this._createKeyBtn(
                        "keyboard_return", "keyboard__key--wide",
                        () => {
                            this.properties.value += "\n";
                            this._updateValueInTarget();
                        });
                    break;
 
                case "space":
                    this._createKeyBtn(
                        "space_bar", "keyboard__key--extra--wide",
                        () => {
                            this.properties.value += " ";
                            this._updateValueInTarget();
                        });
                    break;
 
                case "done":
                    this._createKeyBtn(
                        "check_circle",
                        "keyboard__key--dark",
                        () => {
                            this.close();
                            this._updateValueInTarget();
                        },
                        "keyboard__key--wide"
                    );
                    break;
 
                default:
                    this._createKeyBtn();
                    this.keyElement.textContent =
                        key.toLowerCase();
 
                    this.keyElement
                        .addEventListener(
                            "click",
                            () => {
                                this.properties.value +=
                                    this.properties.capsLock
                                        ? key.toUpperCase()
                                        : key.toLowerCase();
                                this._updateValueInTarget();
                            });
                    break;
            }
 
            fragment.appendChild(this.keyElement);
 
            if (insertLineBreak) {
                fragment
                    .appendChild(document.createElement("br"));
            }
        });
        return fragment;
    },
 
    _updateValueInTarget() {
        this.properties
            .keyboardInputs
            .forEach((keyboard) => {
                keyboard.value =
                    this.properties.value;
            });
    },
 
    _toggleCapsLock() {
        this.properties.capsLock =
            !this.properties.capsLock;
 
        for (let key of this.elements.keys) {
            if (key.childElementCount === 0) {
                key.textContent =
                    this.properties.capsLock
                        ? key.textContent.toUpperCase()
                        : key.textContent.toLowerCase();
            }
        }
    },
 
    open(initialValue, oninput) {
        this.properties.value =
            initialValue || "";
        this.elements.main
            .classList
            .remove("keyboard--hidden");
    },
 
    close() {
        this.properties.value =
            this.properties.value;
        this.elements.main
            .classList.add("keyboard--hidden");
    },
};
 
window.addEventListener("DOMContentLoaded", function () {
    Keyboard.init();
});


HTML




<!-- index.html  -->
<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta name="viewport"
        content="width=device-width,
        initial-scale=1.0" />
    <link rel="stylesheet" href="style.css" />
    <link href=
    <title>
        Virtual Keyboard
    </title>
</head>
 
<body>
    <textarea name="anytext"
        class="text-area use-keyboard-input"
        placeholder="Click me!">
    </textarea>
    <script src="script.js"></script>
</body>
 
</html>


CSS




/* style.css  */
.text-area {
    padding: 5px;
    width: calc(100vw - 30px);
    height: calc(100vh - 295px);
}
 
.keyboard {
    position: fixed;
    left: 0;
    bottom: 0;
    width: 100%;
    padding: 5px 0;
    background: #004134;
    box-shadow: 0 0 50px rgba(0, 0, 0, 0.5);
    transition: bottom 0.4s;
}
 
.keyboard--hidden {
    bottom: -100%;
}
 
.keyboard__keys {
    text-align: center;
}
 
.keyboard__key {
    height: 45px;
    width: 6%;
    max-width: 90px;
    margin: 3px;
    border-radius: 4px;
    border: none;
    background: rgba(255, 255, 255, 0.2);
    color: white;
    font-size: 1.05rem;
    outline: none;
    cursor: pointer;
    display: inline-flex;
    justify-content: center;
    align-items: center;
    vertical-align: top;
    padding: 0;
    -webkit-tap-highlight-color: transparent;
    position: relative;
}
 
.keyboard__key:active {
    background: rgba(255, 255, 255, 0.12);
}
 
.keyboard__key--wide {
    width: 12%;
}
 
.keyboard__key--extra--wide {
    width: 36%;
    max-width: 500px;
}
 
.keyboard__key--activatable::after {
    content: "";
    position: absolute;
    top: 10px;
    right: 10px;
    width: 8px;
    height: 8px;
    background: rgba(0, 0, 0, 0.4);
    border-radius: 50%;
}
 
.keyboard__key--active::after {
    background: #08ff00;
}
 
.keyboard__key--dark {
    background: rgba(0, 0, 0, 0.25);
}


Output:

virtual-keyboard

virtual keyboard



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads