Javascript + css toast notifications
Rus
Eng
Всплывающие уведомления javascript + css
I solve complex technical challenges for Bitrix and 1C—ranging from auditing existing code to configuring complex integrations—with a guarantee of results.
Recommended

Website hosting

If you are choosing hosting for your project, I recommend Timeweb. Modern infrastructure, a wide range of plans from starter options to high-load VPS, and responsive tech support that actually helps instead of sending template replies. I host some of my own projects there and recommend it to my clients.

Go to site Affiliate link. The price remains the same for you.

All English-language materials have been translated fully automatically using the Google service

An excellent solution for pop-up notifications was suggested by the author of the site web3r.ru

javascript

/**
 * Анонимная самовызывающаяся функция-обертка
 * @param {document} d - получает документ
 */
!function(d) {

    "use strict";

    /**
     * Основная функция.
     * @param {Object} [settings] - предвартиельные настройки
     */
    window.note = function(settings) {

        /**
         * Настройки по умолчанию
         */
        settings = Object.assign({},{
            callback:    false,
            content:     "",
            time:        4.5,
            type:        "info"
        }, settings);

        if(!settings.content.length) return;

        /**
         * Функция создания элементов
         * @param {String} name - название DOM-элемента
         * @param {Object} attr - объект с атрибутами
         * @param {Object} append - DOM-элемент, в который будет добавлен новый узел
         * @param {String} [content] - контент DOM-элемента
         */
        var create = function(name, attr, append, content) {
            var node = d.createElement(name);
            for(var val in attr) { if(attr.hasOwnProperty(val)) node.setAttribute(val, attr[val]); }
            if(content) node.insertAdjacentHTML("afterbegin", content);
            append.appendChild(node);
            if(node.classList.contains("note-item-hidden")) node.classList.remove("note-item-hidden");
            return node;
        };

        /**
         * Генерация элементов
         */
        var noteBox = d.getElementById("notes") || create("div", { "id": "notes" }, d.body);
        var noteItem = create("div", {
                "class": "note-item",
                "data-show": "false",
                "role": "alert",
                "data-type": settings.type
            }, noteBox),
            noteItemText = create("div", { "class": "note-item-text" }, noteItem, settings.content),
            noteItemBtn = create("div", {
                "class": "note-item-btn",
                "aria-label": "Скрыть"
            }, noteItem);

        /**
         * Функция проверки видимости алерта во viewport
         * @returns {boolean}
         */
        var isVisible = function() {
            var coords = noteItem.getBoundingClientRect();
            return (
                coords.top >= 0 &&
                coords.left >= 0 &&
                coords.bottom <= (window.innerHeight || d.documentElement.clientHeight) &&
                coords.right <= (window.innerWidth || d.documentElement.clientWidth)
            );
        };

        /**
         * Функция удаления алертов
         * @param {Object} [el] - удаляемый алерт
         */
        var remove = function(el) {
            el = el || noteItem;
            el.setAttribute("data-show","false");
            window.setTimeout(function() {
                el.remove();
            }, 250);
            if(settings.callback) settings.callback(); // callback
        };

        /**
         * Удаление алерта по клику на кнопку
         */
        noteItemBtn.addEventListener("click", function() { remove(); });

        /**
         * Визуальный вывод алерта
         */
        window.setTimeout(function() {
            noteItem.setAttribute("data-show","true");
        }, 250);


        /**
         * Проверка видимости алерта и очистка места при необходимости
         */
        if(!isVisible()) remove(noteBox.firstChild);

        /**
         * Автоматическое удаление алерта спустя заданное время
         */
        window.setTimeout(remove, settings.time * 1000);

    };

}(document);

css

#notes {
    position: fixed;
    top: 72px;
    right: 0;
    width: 100%;
    cursor: default;
    transition: height 0.45s ease-in-out;
    -webkit-transition: height 0.45s ease-in-out;
    pointer-events: none;
    z-index: 10;
}
#notes .note-item {
    max-height: 12em;
    opacity: 1;
    will-change: opacity, transform;
    transition: all 0.2s linear;
    -webkit-transition: all 0.2s linear;
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
    -moz-backface-visibility: hidden;
    -ms-backface-visibility: hidden;
    width: 50vw;
    -webkit-touch-callout: none;
    user-select: none;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    -o-user-select: none;
    z-index: 2;
    pointer-events: auto;
    display: -webkit-box;
    display: -webkit-flex;
    display: -moz-flex;
    display: -ms-flex;
    display: -ms-flexbox;
    display: flex;
    -webkit-align-content: flex-end;
    -ms-flex-line-pack:end;
    align-content: flex-end;
    -webkit-box-align: end;
    -ms-flex-align: end;
    -webkit-align-items: flex-end;
    -moz-align-items: flex-end;
    align-items: flex-end;
    -webkit-align-content: flex-end;
    -ms-flex-line-pack: end;
    align-content: flex-end;
    max-width: 20em;
    font: inherit;
    line-height: 1.25em;
    color: #fff;
    margin: 0;
    transform: translateZ(0);
    -moz-transform: translateZ(0);
    -ms-transform: translateZ(0);
    -webkit-transform: translateZ(0);
    padding: 0.75em 1em;
    margin-left: auto;
    margin-right: 20px;
    margin-top: 10px;
}
@media all and (max-width: 30em) {
    #notes .note-item {
        width: 75vw;
        max-width: none;
    }
}
#notes .note-item[data-show=false] {
    pointer-events: none;
    opacity: 0 !important;
    max-height: 0 !important;
    margin-bottom: 0 !important;
}
#notes .note-item[data-type=info] {
    background-color: rgba(55, 94, 151, 0.72);
}
#notes .note-item[data-type=warn] {
    background-color: rgba(235, 172, 0, 0.72);
    animation: shake 0.9s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
    -webkit-animation: shake 0.9s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
}
#notes .note-item[data-type=error] {
    background-color: rgba(251, 101, 66, 0.72);
    animation: shake 0.54s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
    -webkit-animation: shake 0.54s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
}
#notes .note-item[data-type=success] {
    background-color: rgba(63, 104, 28, 0.72);
}
#notes .note-item .note-item-text {
    flex: auto;
    -webkit-flex: auto;
    -moz-flex: auto;
    -ms-flex: auto;
    padding-right: 0.5em;
    max-width: calc(100% - 1.25em);
    max-width: -webkit-calc(100% - 1.25em);
}
#notes .note-item .note-item-btn {
    width: 1.25em;
    height: 1.25em;
    cursor: pointer;
    background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiB4bWw6c3BhY2U9InByZXNlcnZlIiBmaWxsPSIjZmZmIj48cGF0aCBkPSJNMTguMyw1LjcxTDE4LjMsNS43MWMtMC4zOS0wLjM5LTEuMDItMC4zOS0xLjQxLDBMMTIsMTAuNTlMNy4xMSw1LjdjLTAuMzktMC4zOS0xLjAyLTAuMzktMS40MSwwbDAsMCBjLTAuMzksMC4zOS0wLjM5LDEuMDIsMCwxLjQxTDEwLjU5LDEyTDUuNywxNi44OWMtMC4zOSwwLjM5LTAuMzksMS4wMiwwLDEuNDFoMGMwLjM5LDAuMzksMS4wMiwwLjM5LDEuNDEsMEwxMiwxMy40MWw0Ljg5LDQuODkgYzAuMzksMC4zOSwxLjAyLDAuMzksMS40MSwwbDAsMGMwLjM5LTAuMzksMC4zOS0xLjAyLDAtMS40MUwxMy40MSwxMmw0Ljg5LTQuODlDMTguNjgsNi43MywxOC42OCw2LjA5LDE4LjMsNS43MXoiLz48L3N2Zz4=) no-repeat 0 0/contain;
    transition: opacity 0.2s;
    -webkit-transition: opacity 0.2s;
}
#notes .note-item .note-item-btn:hover {
    opacity: 0.6;
}

@keyframes shake {
    10%, 90% {
        transform: translate3d(-1px, 0, 0);
        -webkit-transform: translate3d(-1px, 0, 0);
        -ms-transform: translate3d(-1px, 0, 0);
    }
    20%, 80% {
        transform: translate3d(2px, 0 0);
        -webkit-transform: translate3d(2px, 0, 0);
        -ms-transform: translate3d(2px, 0, 0);
    }
    30%, 50%, 70% {
        transform: translate3d(-4px, 0, 0);
        -webkit-transform: translate3d(-4px, 0, 0);
        -ms-transform: translate3d(-4px, 0, 0);
    }
    40%, 60% {
        transform: translate3d(4px, 0, 0);
        -webkit-transform: translate3d(4px, 0, 0);
        -ms-transform: translate3d(4px, 0, 0);
    }
}
@-webkit-keyframes shake {
    10%, 90% {
        -webkit-transform: translate3d(-1px, 0, 0);
    }
    20%, 80% {
        -webkit-transform: translate3d(2px, 0, 0);
    }
    30%, 50%, 70% {
        -webkit-transform: translate3d(-4px, 0, 0) t;
    }
    40%, 60% {
        -webkit-transform: translate3d(4px, 0, 0);
    }
}

Use

note({
	content: "<b>Сообщение успешно отправлено</b>",
	type: "success", //success,warn,info,error
	time: 5
});

Source

Aleksandr Tichiy
Author

Aleksandr Tichiy

Fullstack developer · 1C-Bitrix

I build and modernize online stores and corporate portals on 1C-Bitrix. Integrations with 1C, high-load performance, 152-FZ compliance. Writing about architecture and e-commerce.


Comments

There are no comments yet, you can be the first to leave it

Leave a comment

The site uses a comment pre-moderation system, so your message will be published only after approval by the moderator

You are replying to a user's comment

Send

FEEDBACK

Email me

Please message me to discuss the task. I work remotely and officially (as a self-employed professional); my hourly rate is 1,800 RUB, and I can dedicate 3–4 hours a day to the project. I respond quickly, and the consultation is free.

An error occurred while sending, please try again after a while
Message sent successfully

Phones

+7(993) 007-18-96

Email

info@tichiy.ru

Address

Россия, г. Москва

By submitting the form, you automatically confirm that you have read and accept the Privacy Policy site