39

tl;dr

I have an input with type=text which I want to show stars like an input with type=password using only CSS.


Basically I have a form with the following input:

<input type='text' value='hello' id='cake' />

I'm not generating the form, I don't have access to its HTML at all. I do however have access to CSS applied to the page.

What I'd like is for it to behave like type=password , that is - to show up stars for what the user typed rather than the actual text being typed. Basically, I'd want that aspect (the presentation of user input) to look like a type=password field.

Since this seems like a presentation only issue, I figured there has to be a way to do this with CSS since it's in its responsibility domain. However - I have not found such a way. I have to support IE8+ but I'd rather have a solution that works for modern browsers only over no solution at all. Extra points for preventing copy/paste functionality but I can live without that.

Note: In case that was not clear I can not add HTML or JavaScript to the page - only CSS.


(Only thing I've found is this question but it's dealing with a jQuery related issue and it has a JavaScript solution)

Community
  • 1
  • 1
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504

11 Answers11

48

There's an experimental CSS selector called -webkit-text-security (or text-security):

input.pw
{
    -webkit-text-security: disc;
    text-security: disc;
}

It's currently supported by Chrome, Edge, and Safari. However, Firefox doesn't support it yet, so it shouldn't be used in production.

For now, one decent workaround is to use webfonts. You can use any font editing utility like FontForge to create a font with all the characters to be * (or any symbol you want). Then use CSS web fonts to use them as a custom font.

Pikamander2
  • 7,332
  • 3
  • 48
  • 69
ShrekOverflow
  • 6,795
  • 3
  • 37
  • 48
27

You can create a font made only of dots

@font-face
    {
    font-family:'dotsfont';
    src:url('dotsfont.eot');
    src:url('dotsfont.eot?#iefix')  format('embedded-opentype'),
        url('dotsfont.svg#font')    format('svg'),
        url('dotsfont.woff')        format('woff'),
        url('dotsfont.ttf')         format('truetype');
    font-weight:normal;
    font-style:normal;
}

input.myclass
    {-webkit-text-security:disc;font-family:dotsfont;}

This might be what you're looking for...

There are many glyphs to define but there might be a simpler way to do that.. You can create a totally empty font and define only the .notdef glyph (glyph ID 0) which is used as a replacement when another glyph is not defined

As you probably know, it usually looks like this: missing glyph icons

So, you should replace that with a dot/asterisk and test what happens with browsers... because i'm not sure if it does work on all of them (some may want to use their own missing glyph replacement). Let me know if you try...

HTH

14

In WebKit-based browsers you can do so using the -webkit-text-security property. It even allows you to select the shape of the bullets (disc, circle, square).

input.pw {
    -webkit-text-security: disc;
}

Demo

input.pw {
  -webkit-text-security: disc;
}

input.pw2 {
  -webkit-text-security: circle;
}

input.pw3 {
  -webkit-text-security: square;
}
<input type="text" class="pw" value="secret">
<input type="text" class="pw2" value="secret">
<input type="text" class="pw3" value="secret">

However, this is apparently non-standard. At least the Safari CSS docs say it's an "Apple Extension". It works fine in Chrome - obviously - but I don't think any other rendering engine supports it...

Ruslan López
  • 4,433
  • 2
  • 26
  • 37
ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
4

You can make a fake password input with type text using a custom font. the following works in chrome, firefox, edge ...

@font-face {
  font-family: 'password';
  font-style: normal;
  font-weight: 400;
  src: url(https://jsbin-user-assets.s3.amazonaws.com/rafaelcastrocouto/password.ttf);
}

input.key {
  font-family: 'password';
  width: 100px; height: 16px;  
}
<p>Password: <input class="key" type="text" autocomplete="off" /></p>

Thanks to @rafaelcastrocouto Original Answer

Abolfazl Roshanzamir
  • 12,730
  • 5
  • 63
  • 79
1

I ended up in this thread a lot of times recently. My solution is utilizing JQuery input event (though it can also be written in raw JS or even in C# (Blazor) should you need it, the idea would be the same):

The core part is:

if (isPasswordVisible) { // if password is visible, then simply update value stored in the dictionary
    value = newValue;
    passwordInputsValues[$passwordInput.attr("my-guid")] = value;
} else { // else compute and update stored value
    const newValueUntilCaret = newValue.take(caretPosition); // take chars before the caret
    const unchangedCharsAtStart = newValueUntilCaret.takeWhile(c => c === "●").length; // count unchanged chars from the beginning
    const unchangedCharsAtEnd = newValue.skip(caretPosition).length; // count unchanged chars after the caret
    const insertedValue = newValueUntilCaret.skip(unchangedCharsAtStart); // get newly added string if any
    value = oldValue.take(unchangedCharsAtStart) + insertedValue + oldValue.takeLast(unchangedCharsAtEnd); // create new value as concatenation of old value left part, new string and old value right part
    passwordInputsValues[$passwordInput.attr("my-guid")] = value; // store newly created value in the dictionary
    $passwordInput.prop("value", value.split("").map(_ => "●").join("")); // set value of the input to new masked value
    $passwordInput[0].setSelectionRange(caretPosition, caretPosition); // set caret position to match the appropriate position 
}

Below is the complete code of an example password control (I will try to update it if any problems arise):

// Utils 

var guid = () => {
    return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
        const r = Math.random() * 16 | 0;
        const v = c === "x" ? r : r & 0x3 | 0x8;
        return v.toString(16);
    });
}

// Array Extensions

Object.defineProperty(Array.prototype, "skip", {
    value: function (n) {
        if (typeof (n) !== "number") {
            throw new Error("n is not a number");
        }
        return this.slice(n);
    },
    writable: true,
    configurable: true
});

Object.defineProperty(Array.prototype, "take", {
    value: function (n) {
        if (typeof (n) !== "number") {
            throw new Error("n is not a number");
        }
        return this.slice(0, n);
    },
    writable: true,
    configurable: true
});

Object.defineProperty(Array.prototype, "takeLast", {
    value: function (n) {
        if (typeof (n) !== "number") {
            throw new Error("n is not a number");
        }
        return this.slice(Math.max(this.length - n, 0));
    },
    writable: true,
    configurable: true
});

Object.defineProperty(Array.prototype, "takeWhile", {
    value: function (condition) {
        if (typeof (condition) !== "function") {
            throw new Error("condition is not a function");
        }

        const arr = [];
        for (let el of this) {
            if (condition(el))
                arr.push(el);
            else
                break;
        }
        return arr;
    },
    writable: true,
    configurable: true
});

// String Extensions

Object.defineProperty(String.prototype, "skip", {
    value: function (n) {
        return this.split("").skip(n).join("");
    },
    writable: true,
    configurable: true
});

Object.defineProperty(String.prototype, "take", {
    value: function (n) {
        return this.split("").take(n).join("");
    },
    writable: true,
    configurable: true
});

Object.defineProperty(String.prototype, "takeLast", {
    value: function (n) {
        return this.split("").takeLast(n).join("");
    },
    writable: true,
    configurable: true
});

Object.defineProperty(String.prototype, "takeWhile", {
    value: function (condition) {
        return this.split("").takeWhile(condition).join("");
    },
    writable: true,
    configurable: true
});

// JQuery Document Ready

$(document).ready(function() {
    let isPasswordVisible = false;
    const passwordInputsValues = {};

    for (let $pi of $(".my-password-input").toArray().map(pi => $(pi))) {
        const uid = guid();
        $pi.attr("my-guid", uid);
        passwordInputsValues[uid] = $pi.prop("value");
    }
 
    $(document).on("input", ".my-password-input", async function(e) {
        const $passwordInput = $(this);
        const newValue = $passwordInput.prop("value");
        const oldValue = passwordInputsValues[$passwordInput.attr("my-guid")] || ""; // first time it will be undefined
        const caretPosition = Math.max($passwordInput[0].selectionStart, $passwordInput[0].selectionEnd);
        let value;

        if (isPasswordVisible) {
            value = newValue;
            passwordInputsValues[$passwordInput.attr("my-guid")] = value;
        } else {
            const newValueUntilCaret = newValue.take(caretPosition);
            const unchangedCharsAtStart = newValueUntilCaret.takeWhile(c => c === "●").length;
            const unchangedCharsAtEnd = newValue.skip(caretPosition).length;
            const insertedValue = newValueUntilCaret.skip(unchangedCharsAtStart);
            value = oldValue.take(unchangedCharsAtStart) + insertedValue + oldValue.takeLast(unchangedCharsAtEnd);
            passwordInputsValues[$passwordInput.attr("my-guid")] = value;
            $passwordInput.prop("value", value.split("").map(_ => "●").join(""));
            $passwordInput[0].setSelectionRange(caretPosition, caretPosition);
        }
    });

    $(document).on("click", ".my-btn-toggle-password-visibility", function() {
        const $btnTogglePassword = $(this);
        const $iconPasswordShown = $btnTogglePassword.find(".my-icon-password-shown");
        const $iconPasswordHidden = $btnTogglePassword.find(".my-icon-password-hidden");
        const $passwordInput = $btnTogglePassword.parents(".my-input-group").first().children(".my-password-input").first();
        const value = passwordInputsValues[$passwordInput.attr("my-guid")];

        if (!isPasswordVisible) {
            $iconPasswordHidden.removeClass("my-d-flex").addClass("my-d-none");
            $iconPasswordShown.removeClass("my-d-none").addClass("my-d-flex");
            $passwordInput.prop("value", value);
            isPasswordVisible = true;
        } else {
            $iconPasswordShown.removeClass("my-d-flex").addClass("my-d-none");
            $iconPasswordHidden.removeClass("my-d-none").addClass("my-d-flex");
            $passwordInput.prop("value", value.split("").map(_ => "●").join(""));
            isPasswordVisible = false;
        }
    });
});
body {
    padding-top: 0;
    color: white;
    margin: 0;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
    font-size: 16px;
    font-weight: 400;
    line-height: 1.5;
    text-align: left;
    height: 100%;
    max-height: 100%;
    background-image: linear-gradient(rgba(0,0,0,0.2), rgba(0,0,0,0.2)), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEYAAABGCAAAAABURb1YAAAFnklEQVR4AWWXCY4cwXbE6h4JMhCvMPc/ov+3Ox9QsLCGpKlFHILd+UQ559AGDkBSFXWmomonqkL/XuUcIPUcONjHCJyE36KaqNiaRnVCG9TGpgIU9hIfohCBVGj24ammo04lU3Fy0NZDAyZi5AElHjgEGlRbG1WjraIt7TmADQkAaoEHsOXAAaeqat9RVTqjosyEH5W+DQCQt8BzIJMfXJI3e5tGRefSlRn3NrO3scnvNl26FN5RITGNfjm3GM/+FhQgnlQeImC+dEm8rzHVTNGL9EADVsTAIfGJBziRy7RlmcZU1IYpHIj+4JrWym8/XSwzompmFNVOFdTOAAfs61KZ6eXcp57fykQUOxNBmTesz2HpCnCg3UV/bA7VRpWGNqKtrYLTs0ilCjgxiZxjeLC5dDPBFn4Pn2ja6BRUL10DTgET4Focq8rn8casxV4E5tIlZvytqtfivCOKZrqc38G7egnkXecyPZdzubc57VtUnbfL+a0u3b1N3d9Mci7cKocHoh3xihLQ6fXUlgTOOfVkXSUFINoWHhqxE23RTmCqtoEJaITkIrUCkU9fnqpqm+40VSXS3CLaSzfGBb4rPuOSfN0ylLve6/jpcrbL2dTlnOdv5AamKjLvLN1XruMNS/cul/hx8twKpKYRaE2DOp8+c+lW7uVXVQ7Vx0x1G3HXjNocsHCac7NbWc6egwJVHu2kRTVNC2pqv2U4XNsv5/yWJlV9+NJ1C7xluInlcr7rK+Kg+qy7onQqgnbi7UHcS3qXjdw3bO5tumycYlVssMI5EXXpRnatPK362KodtVU60cm+eQT10sVLFwJYlVaf7UGSoi5dQF3DvnTX3UvXTPO8quKH7jsXhm/PxfKWZXqBM5sS33kmKtC31Q05fI095i5IPpyzRXqSy1Sr17p1F7NE8vMtnNbLpVVtk8c0OrfF0sKxHnIpYgHW4puMomTz8mgmrSjpvrxhX97l7LqLpl7bW9BH9/MNzF8XwRqL8/m7c30eFYV5VX3QTquK06XbLt16F4ks+8Z9m6gPtpcuk3OvibCekng4lzMHi9MoqZmKj9tdbQCbc7bcEA+oEJduRNNL1waf1tuI9MDBUK8t3k9uFz3rrqadO9Ln9TL/ezlwDvky3TW7ZmXfpc77TN0yhOXnP939LvVDV9s+tgLTm0TqYd1lea3PRFuVjLa562HdPbCfascGrvO3DMeIATVqVRO8vfHrbupdfo1dzlXUdkVLZsS1mLPG3rWcl+4B1l1537h0VXzU1tyLG7cCu+LSrSqo06hocy3WCcil65qHDbuEYzQN2HpT3jFt9LEFvHTP1nxbXOEkbhkKmd+6BTfVZ/I143z/Fyz6Za92o0I7I6gzfeYAHPwy/Rb43L9TLtMt8CtwW1xvQvbR1g9n7qJRNN1kdxcdH7cM58Szxq679MdLOhE72t6VNEpHHkzwRyjBcGth+dE99pIkVbWaEWmvnQ8Yl7Mp59zpRWXdNo6odrO754Zzvxf/010nP7onb1TR+bgbVPB9PcADJvH/043Kvk0UzLRxQ6UiaeTAcyxYl2lyrrvZv8v2wE7U1uVcST0821jJeIDKWuyxiqnuko7q3+zJYXJ46nV3D67EyL+lQ9F2qkr+3kUafQpwYE8T329p6y7OX1TF97fQv/c+l87zj7Hsgpig4qRLd9fMPs74rLGyCzRbhmVqpy7nqvPmTD1gvKe7b2U8u1QzmtuDuEtbgT3c8QBJveo6cueFkUwv59nVmfFw1jl4/unuOT9qERV76ers8n23z/c8/Xy7a4lwwLplmGusbRp33Up13+ZDN3KPxNVMhY62vUQyRTse6+cKHtZYjIfDh260Cjbb3Vy6R8H8SMBzqSwrsB1UTacoknlnOb8V4JD9Njfpwz/fHjpBUeevcAtcl65sqXPX9D87RUTLc/dfOgAAAABJRU5ErkJggg==);
    background-clip: border-box;
    background-origin: padding-box;
    background-attachment: scroll;
    background-repeat: repeat;
    background-size: auto;
    background-position: left top;
}

.snippet-container {
    background: linear-gradient(135deg, #202020, black);
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 200px;
}

.my-password-input {
    background: linear-gradient(to bottom, #303030, #000000);
    color: white;
    display: block;
    position: relative;
    box-sizing: border-box;
    padding: 5px 9px;
    line-height: 24px;
    height: 34px;
    box-shadow: inset 0 0 0 1px #404040;
    font-size: 16px;
    font-weight: 400;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
    transition: all .15s ease-in-out;
    width: 100%;
    border: none;
}

.my-password-input:enabled:focus {
    color: white;
    box-shadow: inset 0 0 0 1px #404040, 0 0 6px 2px blue;
    outline: none;
}

.my-input-group {
    position: relative;
}

    .my-input-group > .my-input-group-prepend {
        display: flex;
        position: absolute;
        left: 0;
        top: 0;
    }

    .my-input-group > .my-input-group-append {
        display: flex;
        position: absolute;
        right: 0;
        top: 0;
    }

.my-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.my-input-group > .my-input-group-prepend > .my-icon,
.my-input-group > .my-input-group-append > .my-icon {
    width: auto;
    height: 16px;
    max-width: none;
    max-height: 16px;
    flex: 0 0 auto;
    margin: 9px;
}

    .my-input-group > .my-input-group-prepend > .my-icon > svg,
    .my-input-group > .my-input-group-append > .my-icon > svg {
        height: 100%;
        width: auto;
        margin: 0;
        padding: 0;
        overflow: hidden;
    }

.my-input-group > .my-input-group-prepend > .my-btn,
.my-input-group > .my-input-group-append > .my-btn {
    height: 100% !important;
    width: auto;
}

button:enabled {
    cursor: pointer;
}

.my-btn {
    background: linear-gradient(to bottom, #303030, #000000);
    color: white;
    position: relative;
    box-sizing: border-box;
    padding: 5px;
    line-height: 24px;
    height: 34px;
    font-size: 16px;
    font-weight: 400;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
    transition: all .15s ease-in-out;
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    border: none;
    box-shadow: 0 0 0 0 #FFFFFF, inset 0 0 0 1px #404040;
}

.my-btn-primary {
    color: #fff;
    background: linear-gradient(to bottom, #00008B, #000000);
    box-shadow: 0 0 0 0 #FFFFFF, inset 0 0 0 1px #0000FF;
}

    .my-btn-primary:hover:enabled {
        box-shadow: 0 0 6px 2px #FFFFFF, inset 0 0 0 1px #FFFFFF;
        background: linear-gradient(to top, #00008B, #000000);
    }

.my-btn > .my-icon {
    margin: 4px;
    width: auto;
    height: 16px;
    max-width: none;
    max-height: 16px;
    flex: 0 0 auto;
}

    .my-btn > .my-icon > svg {
        height: 100%;
        width: auto;
    }

.my-d-none {
    display: none !important;
}

.my-d-flex {
    display: flex !important;
}

::-webkit-input-placeholder {
    color: #404040;
    font-style: italic;
}

:-moz-placeholder {
    color: #404040;
    font-style: italic;
}

::-moz-placeholder {
    color: #404040;
    font-style: italic;
}

:-ms-input-placeholder {
    color: #404040;
    font-style: italic;
}

::-moz-selection {
    background-color: #f8b700;
    color: #352011;
}

::selection {
    background-color: #f8b700;
    color: #352011;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="snippet-container">
    <div class="my-input-group">
        <input type="text" placeholder="Password..." class="my-password-input" style="padding-left: 38px; padding-right: 47px;">
        <div class="my-input-group-prepend">
            <div class="my-icon" style="">
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="">
                    <path d="M336 32c79.529 0 144 64.471 144 144s-64.471 144-144 144c-18.968 0-37.076-3.675-53.661-10.339L240 352h-48v64h-64v64H32v-80l170.339-170.339C195.675 213.076 192 194.968 192 176c0-79.529 64.471-144 144-144m0-32c-97.184 0-176 78.769-176 176 0 15.307 1.945 30.352 5.798 44.947L7.029 379.716A24.003 24.003 0 0 0 0 396.686V488c0 13.255 10.745 24 24 24h112c13.255 0 24-10.745 24-24v-40h40c13.255 0 24-10.745 24-24v-40h19.314c6.365 0 12.47-2.529 16.971-7.029l30.769-30.769C305.648 350.055 320.693 352 336 352c97.184 0 176-78.769 176-176C512 78.816 433.231 0 336 0zm48 108c11.028 0 20 8.972 20 20s-8.972 20-20 20-20-8.972-20-20 8.972-20 20-20m0-28c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48z" style="fill: white"></path>
                </svg>
            </div>
        </div>
        <div class="my-input-group-append">
            <button class="my-btn my-btn-primary my-btn-toggle-password-visibility" style="width: 38px">
                <div class="my-icon my-icon-password-shown my-d-none" style="">
                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" style="">
                        <path d="M288 288a64 64 0 0 0 0-128c-1 0-1.88.24-2.85.29a47.5 47.5 0 0 1-60.86 60.86c0 1-.29 1.88-.29 2.85a64 64 0 0 0 64 64zm284.52-46.6C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 96a128 128 0 1 1-128 128A128.14 128.14 0 0 1 288 96zm0 320c-107.36 0-205.46-61.31-256-160a294.78 294.78 0 0 1 129.78-129.33C140.91 153.69 128 187.17 128 224a160 160 0 0 0 320 0c0-36.83-12.91-70.31-33.78-97.33A294.78 294.78 0 0 1 544 256c-50.53 98.69-148.64 160-256 160z" style="fill: white"></path>
                    </svg>
                </div>

                <div class="my-icon my-icon-password-hidden" style="">
                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512" style="">
                        <path d="M637 485.25L23 1.75A8 8 0 0 0 11.76 3l-10 12.51A8 8 0 0 0 3 26.75l614 483.5a8 8 0 0 0 11.25-1.25l10-12.51a8 8 0 0 0-1.25-11.24zM320 96a128.14 128.14 0 0 1 128 128c0 21.62-5.9 41.69-15.4 59.57l25.45 20C471.65 280.09 480 253.14 480 224c0-36.83-12.91-70.31-33.78-97.33A294.88 294.88 0 0 1 576.05 256a299.73 299.73 0 0 1-67.77 87.16l25.32 19.94c28.47-26.28 52.87-57.26 70.93-92.51a32.35 32.35 0 0 0 0-29.19C550.3 135.59 442.94 64 320 64a311.23 311.23 0 0 0-130.12 28.43l45.77 36C258.24 108.52 287.56 96 320 96zm60.86 146.83A63.15 63.15 0 0 0 320 160c-1 0-1.89.24-2.85.29a45.11 45.11 0 0 1-.24 32.19zm-217.62-49.16A154.29 154.29 0 0 0 160 224a159.39 159.39 0 0 0 226.27 145.29L356.69 346c-11.7 3.53-23.85 6-36.68 6A128.15 128.15 0 0 1 192 224c0-2.44.59-4.72.72-7.12zM320 416c-107.36 0-205.47-61.31-256-160 17.43-34 41.09-62.72 68.31-86.72l-25.86-20.37c-28.48 26.28-52.87 57.25-70.93 92.5a32.35 32.35 0 0 0 0 29.19C89.71 376.41 197.07 448 320 448a311.25 311.25 0 0 0 130.12-28.43l-29.25-23C389.06 408.84 355.15 416 320 416z" style="fill: white"></path>
                    </svg>
                </div>
            </button>
        </div>
    </div>
</div>
rvnlord
  • 3,487
  • 3
  • 23
  • 32
0

Basically you can do

input { -webkit-text-security: disc; }

inside your css file.

But caution, someone could simply "inspect element" in Chrome and change the css element from "disc" to "none" and real text would be seen clear as day.

As for disabling select/copy refer to this post: How to disable text selection highlighting using CSS?

Community
  • 1
  • 1
Sicha
  • 37
  • 1
  • 3
  • 7
    Someone can change the type to `text` and see it anyway. Or just look at the `.value`. – Benjamin Gruenbaum Sep 15 '16 at 19:01
  • 4
    Yes but that is true even for type="password" field. Alternatively he could use autocomplete="new-password" it's a new feature for chrome, you could read further about it here: [link](https://bugs.chromium.org/p/chromium/issues/detail?id=370363#c7) – Sicha Sep 16 '16 at 12:29
0

This works only for text field (:

input { -webkit-text-security: none; } 
input { -webkit-text-security: circle; } 
input { -webkit-text-security: square; } 
input { -webkit-text-security: disc; /* Default */ }
Walk
  • 1,531
  • 17
  • 21
0

I wanted both input type text and password to look the same while still providing the security of ***** for the password input field

CSS

input[type="text"],
select {
  width: 90%;
  padding: 10px 20px;
  margin: 8px 0;
  display: inline-block;
  border: 1px solid #ccc;
  border-radius: 1px;
  box-sizing: border-box;
}
input[type="password"],
select {
  width: 90%;
  padding: 10px 20px;
  margin: 8px 0;
  display: inline-block;
  border: 1px solid #ccc;
  border-radius: 1px;
  box-sizing: border-box;
}

HTML

<input
    type="text"
    name="email"
    placeholder="user@email.com"
/>

<input
    type="password"
    name="password"
    placeholder="*********************"
/>

jasonleonhard
  • 12,047
  • 89
  • 66
0

I used a font from this project https://github.com/noppa/text-security. Here are styles for "disc" (the same can be done for "circle" or "square")

@font-face {
  font-family: 'text-security-disc';
  src: url('fonts/text-security-disc.woff2') format('woff2'),
    url('fonts/text-security-disc.woff') format('woff');
}

.text-security-disc {
  font-family: text-security-disc;
  /* Use -webkit-text-security if the browser supports it */
  -webkit-text-security: disc;
}
humkins
  • 9,635
  • 11
  • 57
  • 75
0

{ -webkit-text-security: disc; }

It is working fine even in Firefox now , just adding on shrekoverflow's answer

Ashraf Ali
  • 43
  • 5
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/34717812) – Harrison Jul 26 '23 at 16:01
-2

If you want to prevent copy paste functionality then you can use:

-webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: moz-none; -ms-user-select: none; user-select: none;

which will not let others select the text and so they will not be able to copy.

aniruddha
  • 61
  • 5
  • 3
    Why do you believe that's what the OP wants? Seriously, not being able to copy&paste is usually the least important feature of password fields. People looking at your screen not seeing the entered password and the browser not storing it for simple form field autocompletion is what one usually wants. – ThiefMaster Jul 21 '13 at 07:58
  • 2
    That's some good information to be posted on this page. Maybe OP doesn't want to prevent copy & paste, but someone in the future will come here looking for an input field that they want to obscure, and see this copy & paste prevention and incorporate it. @ThiefMaster, why do you believe OP, DenverCoder92, or someone else in the future wouldn't want this information? – Jeff Harris May 24 '18 at 20:26