 #  Build a Native Login Popup Using Only Core Joomla 

 

  ![Build a Native Login Popup Using Only Core Joomla](https://cdn.richeyweb.com/images/articles/build-a-native-login-popup-using-only-core-joomla/native-login-popup.webp)    A login popup for [Joomla](/blog/hosting/cron-vs-joomla-lazy-scheduler-and-webcron "Cron vs Joomla Lazy Scheduler and WebCron") - one that lets visitors sign in on the page they're already on, matches your site's branding, and closes the way users expect - sounds like a premium extension. It isn't. Joomla's core already provides every component needed to build a native login popup: a login module, an AJAX template helper, and the browser's own `<dialog>` element. Your existing module configuration controls the behavior - including where users land after login - exactly as you've set it up. No subscription, no third-party code, no additional attack surface. Just Joomla, doing what Joomla already knows how to do.

This tutorial builds it from scratch - lightweight, maintainable, and fully compatible with [Joomla 4](/blog/development/new-for-2025 "New for 2025"), 5, and 6.

In this guide, we’ll build a lightweight native login popup that:

- Uses your existing mod\_login module exactly as you configured it (any redirects, greeting settings, or post-login behavior will continue to work normally)
- Offers a perfect no-JavaScript fallback (a full login page)
- Remains extremely small, clean, and maintainable
 
This is the Joomla way: leverage the platform’s built-in tools instead of adding unnecessary layers.

## Step 1: Create the Menu Item

Create a new [menu item](/joomla-techniques/youtube-rss-feed-gallery "YouTube RSS Feed Gallery") of type **System Links &gt; URL**.

Set the **Link** field to:

text



 

 

 ```
<span>index.php?option=com_ajax&template=YourTemplateName&method=loginForm&format=html</span>
```

 

 



 

 

Replace YourTemplateName with the actual folder name of your active template (for example: cassiopeia or the name of your child template).

In the **Link Type** tab, add the CSS class **dialog-login** in the **Link CSS Style** field.

This ensures that visitors without [JavaScript](/test-article "Shader BG Test") receive a fully functional login page, while those with JavaScript get the popup experience.

## Step 2: Create the Template Helper (helper.php)

In the root of your template folder (strongly recommended: use a **child template**), create or update the file helper.php:

PHP



 

 

 ```
<span><?php</span>
<span>defined('_JEXEC') or die;</span>
<span></span>
<span>use Joomla\CMS\Factory;</span>
<span>use Joomla\CMS\Helper\ModuleHelper;</span>
<span>use Joomla\CMS\Language\Text;</span>
<span>use Joomla\CMS\HTML\HTMLHelper;</span>
<span>use Joomla\Registry\Registry;</span>
<span></span>
<span>class TplCassiopeiaHelper   // Change "Cassiopeia" to match your actual template folder name</span>
<span>{</span>
<span>    public static function loginFormAjax()</span>
<span>    {</span>
<span>        $app = Factory::getApplication();</span>
<span>        $input = $app->getInput();</span>
<span></span>
<span>        $moduleId = $input->getInt('moduleid', 0);</span>
<span></span>
<span>        $module = ModuleHelper::getModule('mod_login');</span>
<span></span>
<span>        if (empty($module->id) && $moduleId) {</span>
<span>            $module = ModuleHelper::getModuleById($moduleId);</span>
<span>        }</span>
<span></span>
<span>        if (empty($module)) {</span>
<span>            return '<div class="alert alert-danger">' . Text::_('MOD_LOGIN_MODULE_NOT_FOUND') . '</div>';</span>
<span>        }</span>
<span></span>
<span>        // Optional tweaks for better popup presentation while respecting your module settings<br></br><br></br>        // if you want to redirect to a specific menu item</span>
<span>        $params = new Registry($module->params ?? '{}');</span>
<span>        $params->set('show_login_form', 1);</span>
<span>        $params->set('greeting', 0);   // Change to 1 if you prefer greeting when logged in<br></br></span>        $params->set('login', numeric-menu-id-here);<br></br>        $module->params = $params->__toString();<br></br><br></br>        // if you want to stay on the current page<br></br>        $referrer = $input->server->get('HTTP_REFERER', '', 'string');<br></br>        if($referrer) {<br></br>          $base64Referrer = base64_encode($referrer);<br></br>          $find = '/name="return" value="[^"]*"/i';<br></br>          $replace = 'name="return" value="'.$base64Referrer.'"';<br></br>          $html = preg_replace($find, $replace, $html);<br></br>        }
<span></span>
<span>        $attribs = ['style' => 'none'];</span>
<span></span>
<span>        $html = ModuleHelper::renderModule($module, $attribs);</span>
<span></span>
<span>        // Handle potential session token timeout (especially useful on cached pages)</span>
<span>        $timeout = $app->get('lifetime', 15) * 60 * 1000; // in milliseconds</span>
<span>        $timeoutTag = '<script type="application/json" id="loginTokenTimeout">' . json_encode(['timeout' => $timeout]) . '</script>';</span>
<span></span>
<span>        return '<div class="joomla-native-login-popup">' . $html . $timeoutTag . '</div>';</span>
<span>    }</span>
<span>}</span>
```

 

Pay close attention to the 2 options you have for redirect. You can stay on the page - or you can type the menu id of the page you'd like your users to land on. Pick one or the other! If you leave the script as-is - you'll always redirect to the current page (because that gets set last).

 



 

 

## Step 3: Add the JavaScript

Most modern Joomla templates support a [user.js](/joomla-techniques/build-a-clean-joomla-header-search-popup-in-minutes-for-free "Build a Clean Joomla Header Search Popup in Minutes - For Free") file that loads automatically. Add the following to your template’s user.js (or include it via your template’s script loader):

JavaScript



 

 

 ```
<span>var initLoginDialog = function() {</span>
<span>    document.addEventListener('click', function (e) {</span>
<span>        const link = e.target.closest('a.dialog-login');</span>
<span>        if (!link) return;</span>
<span></span>
<span>        e.preventDefault();</span>
<span></span>
<span>        let ajaxUrl = link.href.replace(/format=html/i, 'format=raw');</span>
<span>        if (ajaxUrl === link.href) {</span>
<span>            ajaxUrl += (ajaxUrl.includes('?') ? '&' : '?') + 'format=raw';</span>
<span>        }</span>
<span></span>
<span>        let dialog = document.getElementById('joomlaLoginDialog');</span>
<span>        if (!dialog) {</span>
<span>            dialog = document.createElement('dialog');</span>
<span>            dialog.id = 'joomlaLoginDialog';</span>
<span>            dialog.setAttribute('closedby', 'any');</span>
<span>            dialog.style.cssText = `</span>
<span>                width: 420px;</span>
<span>                max-width: 95vw;</span>
<span>                border: none;</span>
<span>                border-radius: 12px;</span>
<span>                padding: 0;</span>
<span>                box-shadow: 0 15px 40px rgba(0, 0, 0, 0.25);</span>
<span>                background: white;</span>
<span>            `;</span>
<span>            document.body.appendChild(dialog);</span>
<span>        }</span>
<span></span>
<span>        dialog.innerHTML = `</span>
<span>            <div style="padding: 40px 20px; text-align: center; font-family: system-ui, sans-serif;"></span>
<span>                <div style="margin-bottom: 16px; color: #666;">Loading login form...</div></span>
<span>                <div style="width: 36px; height: 36px; border: 5px solid #f0f0f0; border-top: 5px solid #0d6efd; </span>
<span>                            border-radius: 50%; animation: spin 0.9s linear infinite; margin: 0 auto;"></div></span>
<span>            </div></span>
<span>            <style>@keyframes spin { to { transform: rotate(360deg); } }</style></span>
<span>        `;</span>
<span></span>
<span>        dialog.showModal();</span>
<span></span>
<span>        fetch(ajaxUrl)</span>
<span>            .then(response => {</span>
<span>                if (!response.ok) throw new Error('Failed to load');</span>
<span>                return response.text();</span>
<span>            })</span>
<span>            .then(html => {</span>
<span>                dialog.innerHTML = `</span>
<span>                    <div style="position: relative; padding: 20px;"></span>
<span>                        <button onclick="this.closest('dialog').close()" </span>
<span>                                style="position: absolute; top: 12px; right: 16px; font-size: 28px; </span>
<span>                                    background: none; border: none; cursor: pointer; color: #999; line-height: 1;"></span>
<span>                            ×</span>
<span>                        </button></span>
<span>                        <div class="joomla-native-login-popup">${html}</div></span>
<span>                    </div></span>
<span>                `;</span>
<span></span>
<span>                // Auto-close dialog if login token expires (helpful for cached pages)</span>
<span>                const timeoutScript = dialog.querySelector('#loginTokenTimeout');</span>
<span>                if (timeoutScript) {</span>
<span>                    try {</span>
<span>                        const data = JSON.parse(timeoutScript.textContent);</span>
<span>                        if (data.timeout) {</span>
<span>                            setTimeout(() => {</span>
<span>                                dialog.close();</span>
<span>                                alert('Your login session has expired. Please try logging in again.');</span>
<span>                            }, data.timeout);</span>
<span>                        }</span>
<span>                    } catch (err) {</span>
<span>                        console.log('Failed to parse login token timeout:', err);</span>
<span>                    }</span>
<span>                }</span>
<span>            })</span>
<span>            .catch(() => {</span>
<span>                dialog.innerHTML = `</span>
<span>                    <div style="padding: 40px 20px; text-align: center; color: #c00;"></span>
<span>                        Could not load the login form.<br><br></span>
<span>                        <button onclick="this.closest('dialog').close()">Close</button></span>
<span>                    </div></span>
<span>                `;</span>
<span>            });</span>
<span>    });</span>
<span>};</span>
<span></span>
<span>window.addEventListener('DOMContentLoaded', initLoginDialog);</span>
```

 



 



 

 

## Login Popup Final Touches

Add some custom CSS targeting .joomla-native-login-popup to fine-tune spacing, button styles, and overall appearance so the form blends seamlessly with your site.

Logout needs to be handled separately. The login link will display the logout button, but will redirect you to a raw version of the login module - so your best bet is to set the login menu item to only display for guest access levels, then create a separate logout button only displayed for registered access levels.

## Official Documentation

For more details on using [com\_ajax](/blog/hosting/varnish-and-joomla "Varnish and Joomla") with templates, refer to the official Joomla manual:

**Using com\_ajax for Modules, Plugins and Templates:** [https://manual.joomla.org/docs/4.4/general-concepts/javascript/com-ajax/](https://manual.joomla.org/docs/4.4/general-concepts/javascript/com-ajax/ "Using com_ajax for Modules, Plugins and Templates")

This page explains the template helper pattern, URL structure, and naming conventions we used here.

HTML dialog element (MDN Web Docs): [https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog "&lt;dialog&gt;: The Dialog element")

These two resources cover the key native technologies used in this technique.

## Why This Approach Wins

This solution is deliberately minimal - just one small helper file and a few lines of vanilla JavaScript. It delivers a modern popup experience while fully respecting Joomla’s core login system and your existing module configuration.

Joomla doesn’t need extra extensions for everyday modern features. It just needs us to explore its tools and share clean, reusable techniques with the community.

## Login Popup Demo? Absolutely!

[Joomla Native Login Popup Demo](/component/ajax/?template=cassiopeia&method=loginForm&format=html)

## Frequently Asked Questions:

Does this work with Joomla's existing login module settings?Yes. The popup loads your existing mod\_login module exactly as configured — including post-login redirects, greeting settings, and any other parameters you've set. Nothing is overridden except presentation.

Citation:[Help5.x:Site Modules: Login](https://docs.joomla.org/Help5.x:Site_Modules:_Login/en)

What happens if JavaScript is disabled?The menu item links directly to a fully functional login page. Visitors without JavaScript get a normal login experience — no broken UI, no dead links. The popup is a progressive enhancement, not a dependency.

Citation:[MDN Web Docs — Progressive Enhancement](https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement)

What is com\_ajax and why is it used here?com\_ajax is a Joomla core component that provides a standardized way to make AJAX requests to modules, plugins, and templates without building a custom component. It's used here to load the login form into the popup without a full page reload.

Citation:[Using com\_ajax for Modules, Plugins and Templates](https://manual.joomla.org/docs/4.4/general-concepts/javascript/com-ajax/)

Why use the HTML dialog element instead of a custom modal?The native element is built into modern browsers and handles accessibility, focus trapping, keyboard dismissal, and backdrop rendering automatically — without a single line of library code. It's the right tool for this job in 2025 and beyond.

Citation:[dialog: The Dialog element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog)

Does this require a child template?Strongly recommended but not strictly required. Using a child template ensures that your helper.php file survives Joomla template updates without being overwritten. Modifying a parent template directly risks losing your changes on the next update.

Citation:[J4.x:Child Templates](https://docs.joomla.org/J4.x:Child_Templates/en)

Will this work with third-party login plugins like social login extensions?If your social login extension integrates with mod\_login and renders inside the standard module output, it will appear in the popup. Extensions that redirect to external OAuth flows will follow their normal behavior after the popup opens.

Citation:[J4.x:Creating an Authentication Plugin for Joomla](https://docs.joomla.org/J4.x:Creating_an_Authentication_Plugin_for_Joomla)

Is this approach secure?Yes. The login form is rendered by Joomla's own mod\_login module and submitted through Joomla's standard authentication system. The CSRF token, session handling, and all security mechanisms remain fully intact. No authentication logic is reimplemented.

Citation:[How to add CSRF anti-spoofing to forms](https://docs.joomla.org/How_to_add_CSRF_anti-spoofing_to_forms)

Does the closedby="any" attribute work in all browsers?closedby="any" is a recent addition to the HTML specification and is supported in modern browsers. In browsers that don't yet support it, the dialog still closes via the × button or the Escape key — the click-outside behavior degrades gracefully.

Citation:[MDN Web Docs — HTMLDialogElement: closedBy property](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/closedBy)

Can I style the popup to match my template?Yes. The popup wrapper carries the class joomla-native-login-popup and the dialog element can be targeted directly in your template's user.css. All inline styles in the JavaScript are intentional defaults — they're fully overridable with standard CSS specificity.

Citation:[MDN Web Docs — CSS Specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Cascade/Specificity)

Does this work on cached pages?The session token timeout handler addresses the most common caching issue — if the page has been cached and the login token has expired, the popup will alert the user rather than silently failing. For heavily cached sites, ensure mod\_login is excluded from page caching.

Citation:[Joomla! Documentation — Cache](https://docs.joomla.org/Cache)



- [      email ](mailto:?subject=Build+a+Native+Login+Popup+Using+Only+Core+Joomla&body=https%3A%2F%2Fwww.richeyweb.com%2Fjoomla-techniques%2Fbuild-a-native-login-popup-using-only-core-joomla)
- [      facebook ](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fwww.richeyweb.com%2Fjoomla-techniques%2Fbuild-a-native-login-popup-using-only-core-joomla)
- [      x-twitter ](https://twitter.com/intent/tweet?text=Build+a+Native+Login+Popup+Using+Only+Core+Joomla%3A+https%3A%2F%2Fwww.richeyweb.com%2Fjoomla-techniques%2Fbuild-a-native-login-popup-using-only-core-joomla)
- [      linkedin ](http://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fwww.richeyweb.com%2Fjoomla-techniques%2Fbuild-a-native-login-popup-using-only-core-joomla&title=Build+a+Native+Login+Popup+Using+Only+Core+Joomla&summary=A+login+popup+for+Joomla+-+one+that+lets+visitors...)
- [      pinterest ](http://pinterest.com/pin/create/button/?url=https%3A%2F%2Fwww.richeyweb.com%2Fjoomla-techniques%2Fbuild-a-native-login-popup-using-only-core-joomla&media=https%3A%2F%2Fcdn.joomla.org%2Fimages%2Fjoomla-org-og.jpg&description=Build+a+Native+Login+Popup+Using+Only+Core+Joomla)
 


 

   [  Next article: Speed Up Your Joomla Workflow with a Custom Administrator Menu  Speed Up Your Joomla Workflow with a Custom Administrator Menu  ](/joomla-techniques/speed-up-your-joomla-workflow-with-a-custom-administrator-menu)  

##### We Value Your Privacy

 

We use cookies to enhance your experience and for traffic analysis. By continuing to visit this site you agree to our use of cookies.

[Privacy Policy](/privacy-policy)

 Details 

###### Google Tag Manager Items

- Ad Storage
- Ad User Data
- Ad Personalization
- Analytics Storage
- Functionality Storage
- Personalization Storage
- Security Storage
 
 

 

 

 

 

 Decline Accept
```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://www.richeyweb.com/#organization","name":"RicheyWeb","url":"https://www.richeyweb.com/","logo":{"@type":"ImageObject","url":"https://www.richeyweb.com/images/logo/richeyweb.svg","contentUrl":"https://www.richeyweb.com/images/logo/richeyweb.svg","width":{"@type":"QuantitativeValue","value":38,"unitCode":"PX"},"height":{"@type":"QuantitativeValue","value":38,"unitCode":"PX"},"@id":"https://www.richeyweb.com/#logo"},"image":{"@id":"https://www.richeyweb.com/#logo"},"sameAs":["https://x.com/ComRicheyweb","https://www.facebook.com/RicheyWebDev/","https://www.youtube.com/channel/UCxnVG8BwOvQRO7hVqNX7T2g","https://community.joomla.org/service-providers-directory/listings/115:richeyweb.html"],"description":"RicheyWeb is a custom software developer specializing in Joomla extensions.","ContactPoint":[{"@type":"ContactPoint","url":"https://www.richeyweb.com/contact-us","telephone":"903-873-8460","contactType":"Owner/Administrator","areaServed":["United States",{"@type":"Country","name":"United States","sameAs":["https://en.wikipedia.org/wiki/United_States","https://www.wikidata.org/wiki/Q30","https://g.co/kg/m/09c7w0"]},"European Union",{"@type":"AdministrativeArea","name":"European Union","sameAs":["https://en.wikipedia.org/wiki/European_Union","https://www.wikidata.org/wiki/Q458","https://g.co/kg/m/0_6t_z8"]},"United Kingdom",{"@type":"Country","name":"United Kingdom","sameAs":["https://en.wikipedia.org/wiki/United_Kingdom","https://www.wikidata.org/wiki/Q145","https://g.co/kg/m/07ssc"]},"Australia",{"@type":"Country","name":"Australia","sameAs":["https://en.wikipedia.org/wiki/Australia","https://www.wikidata.org/wiki/Q408","https://g.co/kg/m/0chghy"]},"Canada",{"@type":"Country","name":"Canada","sameAs":["https://en.wikipedia.org/wiki/Canada","https://www.wikidata.org/wiki/Q16","https://g.co/kg/m/0d060g"]},"Russia",{"@type":"Country","name":"Russia","sameAs":["https://en.wikipedia.org/wiki/Russia","https://www.wikidata.org/wiki/Q159","https://g.co/kg/m/06bnz"]},"China",{"@type":"Country","name":"China","sameAs":["https://en.wikipedia.org/wiki/China","https://www.wikidata.org/wiki/Q148","https://g.co/kg/m/0d05w3"]}],"availableLanguage":"en"},{"@type":"ContactPoint","url":"https://www.richeyweb.com/bugs","telephone":"903-873-8460","contactType":"Technical Support","areaServed":["United States",{"@type":"Country","name":"United States","sameAs":["https://en.wikipedia.org/wiki/United_States","https://www.wikidata.org/wiki/Q30","https://g.co/kg/m/09c7w0"]},"European Union",{"@type":"AdministrativeArea","name":"European Union","sameAs":["https://en.wikipedia.org/wiki/European_Union","https://www.wikidata.org/wiki/Q458","https://g.co/kg/m/0_6t_z8"]},"United Kingdom",{"@type":"Country","name":"United Kingdom","sameAs":["https://en.wikipedia.org/wiki/United_Kingdom","https://www.wikidata.org/wiki/Q145","https://g.co/kg/m/07ssc"]},"Australia",{"@type":"Country","name":"Australia","sameAs":["https://en.wikipedia.org/wiki/Australia","https://www.wikidata.org/wiki/Q408","https://g.co/kg/m/0chghy"]},"Canada",{"@type":"Country","name":"Canada","sameAs":["https://en.wikipedia.org/wiki/Canada","https://www.wikidata.org/wiki/Q16","https://g.co/kg/m/0d060g"]},"Russia",{"@type":"Country","name":"Russia","sameAs":["https://en.wikipedia.org/wiki/Russia","https://www.wikidata.org/wiki/Q159","https://g.co/kg/m/06bnz"]},"China",{"@type":"Country","name":"China","sameAs":["https://en.wikipedia.org/wiki/China","https://www.wikidata.org/wiki/Q148","https://g.co/kg/m/0d05w3"]}],"availableLanguage":"en"}],"knowsAbout":["Computer programming",{"@type":"Thing","name":"Computer programming","sameAs":["https://en.wikipedia.org/wiki/Computer_programming","https://www.wikidata.org/wiki/Q80006","https://g.co/kg/m/01mf_"]},"PHP",{"@type":"Thing","name":"PHP","sameAs":["https://en.wikipedia.org/wiki/PHP","https://www.wikidata.org/wiki/Q59","https://g.co/kg/m/060kv"]},"JavaScript",{"@type":"Thing","name":"JavaScript","sameAs":["https://en.wikipedia.org/wiki/JavaScript","https://www.wikidata.org/wiki/Q2005","https://g.co/kg/m/02p97"]},"arduino","Computer forensics",{"@type":"Thing","name":"Computer forensics","sameAs":["https://en.wikipedia.org/wiki/Computer_forensics","https://www.wikidata.org/wiki/Q878553","https://g.co/kg/m/02wxbd"]},"White hat",{"@type":"Thing","name":"White hat","sameAs":["https://en.wikipedia.org/wiki/White_hat_(computer_security)","https://www.wikidata.org/wiki/Q7995625","https://g.co/kg/m/03ns_5"]},"Search engine optimization",{"@type":"Thing","name":"Search engine optimization","sameAs":["https://en.wikipedia.org/wiki/Search_engine_optimization","https://www.wikidata.org/wiki/Q180711","https://g.co/kg/m/019qb_"]},"Search engine marketing",{"@type":"Thing","name":"Search engine marketing","sameAs":["https://en.wikipedia.org/wiki/Search_engine_marketing","https://www.wikidata.org/wiki/Q846132","https://g.co/kg/m/06mw8r"]},"Digital marketing",{"@type":"Thing","name":"Digital marketing","sameAs":["https://en.wikipedia.org/wiki/Digital_marketing","https://www.wikidata.org/wiki/Q1323528","https://g.co/kg/g/122hcnps"]},"Web hosting service",{"@type":"Thing","name":"Web hosting service","sameAs":["https://en.wikipedia.org/wiki/Web_hosting_service","https://www.wikidata.org/wiki/Q5892272","https://g.co/kg/m/014pz4"]},"Email hosting service",{"@type":"Thing","name":"Email hosting service","sameAs":["https://en.wikipedia.org/wiki/Email_hosting_service","https://www.wikidata.org/wiki/Q5368818","https://g.co/kg/m/09w60m"]},"Internet hosting service",{"@type":"Thing","name":"Internet hosting service","sameAs":["https://en.wikipedia.org/wiki/Internet_hosting_service","https://www.wikidata.org/wiki/Q1210425","https://g.co/kg/m/09w5yw"]},"Virtual hosting",{"@type":"Thing","name":"Virtual hosting","sameAs":["https://en.wikipedia.org/wiki/Virtual_hosting","https://www.wikidata.org/wiki/Q588365","https://g.co/kg/m/024mvh"]},"Web performance",{"@type":"Thing","name":"Web performance","sameAs":["https://en.wikipedia.org/wiki/Web_performance","https://www.wikidata.org/wiki/Q7978612","https://g.co/kg/m/0gfj3f1"]},"Web content management system",{"@type":"Thing","name":"Web content management system","sameAs":["https://en.wikipedia.org/wiki/Web_content_management_system","https://www.wikidata.org/wiki/Q45211","https://g.co/kg/m/0615s2"]},"Content management system",{"@type":"Thing","name":"Content management system","sameAs":["https://en.wikipedia.org/wiki/Content_management_system","https://www.wikidata.org/wiki/Q131093","https://g.co/kg/m/0k23c"]},"General Data Protection Regulation",{"@type":"Thing","name":"General Data Protection Regulation","sameAs":["https://en.wikipedia.org/wiki/General_Data_Protection_Regulation","https://www.wikidata.org/wiki/Q1172506","https://g.co/kg/m/0pk_7xs"]},"SERP",{"@type":"Thing","name":"SERP","sameAs":["https://en.wikipedia.org/wiki/SERP","https://www.wikidata.org/wiki/Q2205811","https://g.co/kg/g/11c5szp7kc"]},"Artificial intelligence",{"@type":"Thing","name":"Artificial intelligence","sameAs":["https://en.wikipedia.org/wiki/Artificial_intelligence","https://www.wikidata.org/wiki/Q11660","https://g.co/kg/m/0mkz"]},"Prompt engineering",{"@type":"Thing","name":"Prompt engineering","sameAs":["https://en.wikipedia.org/wiki/Prompt_engineering","https://www.wikidata.org/wiki/Q108941486","https://g.co/kg/g/11p6kpgt_n"]},"E-learning",{"@type":"Thing","name":"E-learning","sameAs":["https://en.wikipedia.org/wiki/E-learning_(theory)","https://www.wikidata.org/wiki/Q182250","https://g.co/kg/g/122czm1f"]},"Sharable Content Object Reference Model",{"@type":"Thing","name":"Sharable Content Object Reference Model","sameAs":["https://en.wikipedia.org/wiki/Sharable_Content_Object_Reference_Model","https://www.wikidata.org/wiki/Q827811","https://g.co/kg/m/06_40"]},"Experience API",{"@type":"Thing","name":"Experience API","sameAs":["https://en.wikipedia.org/wiki/Experience_API","https://www.wikidata.org/wiki/Q7807728","https://g.co/kg/g/1yw9ktxr8"]},"Joomla",{"@type":"Thing","name":"Joomla","sameAs":["https://en.wikipedia.org/wiki/Joomla","https://www.wikidata.org/wiki/Q13167","https://g.co/kg/m/07qb81"]},"Nginx",{"@type":"Thing","name":"Nginx","sameAs":["https://en.wikipedia.org/wiki/Nginx","https://www.wikidata.org/wiki/Q306144","https://g.co/kg/m/02qft91"]},"MySQL",{"@type":"Thing","name":"MySQL","sameAs":["https://en.wikipedia.org/wiki/MySQL","https://www.wikidata.org/wiki/Q850","https://g.co/kg/m/04y3k"]}],"areaServed":["United States",{"@type":"Country","name":"United States","sameAs":["https://en.wikipedia.org/wiki/United_States","https://www.wikidata.org/wiki/Q30","https://g.co/kg/m/09c7w0"]},"European Union",{"@type":"AdministrativeArea","name":"European Union","sameAs":["https://en.wikipedia.org/wiki/European_Union","https://www.wikidata.org/wiki/Q458","https://g.co/kg/m/0_6t_z8"]},"United Kingdom",{"@type":"Country","name":"United Kingdom","sameAs":["https://en.wikipedia.org/wiki/United_Kingdom","https://www.wikidata.org/wiki/Q145","https://g.co/kg/m/07ssc"]},"Australia",{"@type":"Country","name":"Australia","sameAs":["https://en.wikipedia.org/wiki/Australia","https://www.wikidata.org/wiki/Q408","https://g.co/kg/m/0chghy"]},"Canada",{"@type":"Country","name":"Canada","sameAs":["https://en.wikipedia.org/wiki/Canada","https://www.wikidata.org/wiki/Q16","https://g.co/kg/m/0d060g"]},"Russia",{"@type":"Country","name":"Russia","sameAs":["https://en.wikipedia.org/wiki/Russia","https://www.wikidata.org/wiki/Q159","https://g.co/kg/m/06bnz"]},"China",{"@type":"Country","name":"China","sameAs":["https://en.wikipedia.org/wiki/China","https://www.wikidata.org/wiki/Q148","https://g.co/kg/m/0d05w3"]}],"memberOf":["Mensa International",{"@type":"Organization","name":"Mensa International","sameAs":["https://en.wikipedia.org/wiki/Mensa_International","https://www.wikidata.org/wiki/Q184194","https://g.co/kg/m/0140pf"]},"National Rifle Association",{"@type":"Organization","name":"National Rifle Association","sameAs":["https://en.wikipedia.org/wiki/National_Rifle_Association","https://www.wikidata.org/wiki/Q863259","https://g.co/kg/m/0j6f9"]},"CompTIA",{"@type":"Organization","name":"CompTIA","sameAs":["https://en.wikipedia.org/wiki/CompTIA","https://www.wikidata.org/wiki/Q597534","https://g.co/kg/m/040shq"]},"ISFCE LLC",{"@type":"Organization","name":"ISFCE LLC","sameAs":["https://isfce.com","https://g.co/kg/g/11wxm5r0rg"]}],"hasCredential":[{"@type":"EducationalOccupationalCredential","name":"Joomla 3 Certified Administrator","credentialCategory":"Certification","description":"Administrator Exam is the first available Joomla! certification exam","recognizedBy":{"@type":"Organization","name":"Open Source Matters, Inc.","sameAs":["https://en.wikipedia.org/wiki/Open_Source_Matters,_Inc.","https://g.co/kg/g/11f00wvjhz"]},"url":"https://certification.joomla.org/certified-user-directory/michael-richey","about":["Content management system",{"@type":"Thing","name":"Content management system","sameAs":["https://en.wikipedia.org/wiki/Content_management_system","https://www.wikidata.org/wiki/Q131093","https://g.co/kg/m/0k23c"]},"Web content management system",{"@type":"Thing","name":"Web content management system","sameAs":["https://en.wikipedia.org/wiki/Web_content_management_system","https://www.wikidata.org/wiki/Q45211","https://g.co/kg/m/0615s2"]},"Joomla",{"@type":"Thing","name":"Joomla","sameAs":["https://en.wikipedia.org/wiki/Joomla","https://www.wikidata.org/wiki/Q13167","https://g.co/kg/m/07qb81"]}],"educationalLevel":"expert","image":{"@type":"ImageObject","url":"https://www.richeyweb.com/images/contact/badge.webp","contentUrl":"https://www.richeyweb.com/images/contact/badge.webp","width":{"@type":"QuantitativeValue","value":300,"unitCode":"PX"},"height":{"@type":"QuantitativeValue","value":86,"unitCode":"PX"},"caption":"Joomla 3 Certified Administrator"}},{"@type":"EducationalOccupationalCredential","name":"Certified Computer Examiner","credentialCategory":"Certification","description":"Internationally recognized computer forensics certifiecation","recognizedBy":{"@type":"Organization","name":"ISFCE LLC","sameAs":["https://en.wikipedia.org/wiki/ISFCE_LLC","https://g.co/kg/g/11wxm5r0rg"]},"url":"https://isfce.com/","about":["Digital forensics",{"@type":"Thing","name":"Digital forensics","sameAs":["https://en.wikipedia.org/wiki/Digital_forensics","https://www.wikidata.org/wiki/Q3246940","https://g.co/kg/m/0cnxzfx"]},"Computer forensics",{"@type":"Thing","name":"Computer forensics","sameAs":["https://en.wikipedia.org/wiki/Computer_forensics","https://www.wikidata.org/wiki/Q878553","https://g.co/kg/m/02wxbd"]},"Mobile device forensics",{"@type":"Thing","name":"Mobile device forensics","sameAs":["https://en.wikipedia.org/wiki/Mobile_device_forensics","https://www.wikidata.org/wiki/Q6887097","https://g.co/kg/m/06zp3tp"]},"Network forensics",{"@type":"Thing","name":"Network forensics","sameAs":["https://en.wikipedia.org/wiki/Network_forensics","https://www.wikidata.org/wiki/Q7001032","https://g.co/kg/m/05pb280"]},"Database forensics",{"@type":"Thing","name":"Database forensics","sameAs":["https://en.wikipedia.org/wiki/Database_forensics","https://www.wikidata.org/wiki/Q5227405","https://g.co/kg/m/0cgqsy"]}],"educationalLevel":"expert","image":{"@type":"ImageObject","url":"https://www.richeyweb.com/images/contact/isfce-cce.webp","contentUrl":"https://www.richeyweb.com/images/contact/isfce-cce.webp","width":{"@type":"QuantitativeValue","value":150,"unitCode":"PX"},"height":{"@type":"QuantitativeValue","value":150,"unitCode":"PX"},"caption":"Certified Computer Examiner"}}],"hasOfferCatalog":{"@type":"OfferCatalog","name":"Web Services","itemListElement":[{"@type":"Offer","itemOffered":{"@type":"Service","name":"Hosting"}},{"@type":"Offer","itemOffered":{"@type":"Service","name":"Development"}},{"@type":"Offer","itemOffered":{"@type":"Service","name":"Search Engine Optimization"}}]}},{"@type":"WebSite","@id":"https://www.richeyweb.com/#website","url":"https://www.richeyweb.com/","name":"RicheyWeb","publisher":{"@id":"https://www.richeyweb.com/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://www.richeyweb.com/search?q={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string","valueMaxLength":256,"valueMinLength":2,"valuePattern":"^[A-Za-z0-9\\s]+$"}},"creator":{"@id":"https://www.richeyweb.com/#organization"},"copyrightHolder":{"@id":"https://www.richeyweb.com/#organization"}},{"@type":"WebPage","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#webpage","url":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla","name":"Build a Native Login Popup Using Only Core Joomla","description":"Build a native login popup using only core Joomla 4-6 features like mod_login, AJAX helpers, and HTML dialog.  Pure Joomla - no extensions needed.","isPartOf":{"@id":"https://www.richeyweb.com/#website"},"about":{"@id":"https://www.richeyweb.com/#organization"},"inLanguage":"en-GB"},{"@type":"Article","image":{"@type":"ImageObject","url":"https://www.richeyweb.com/images/articles/build-a-native-login-popup-using-only-core-joomla/native-login-popup.webp","contentUrl":"https://www.richeyweb.com/images/articles/build-a-native-login-popup-using-only-core-joomla/native-login-popup.webp","width":{"@type":"QuantitativeValue","value":976,"unitCode":"PX"},"height":{"@type":"QuantitativeValue","value":549,"unitCode":"PX"},"caption":"Build a Native Login Popup Using Only Core Joomla","representativeOfPage":true},"headline":"Build a Native Login Popup Using Only Core Joomla","description":"Build a native login popup using only core Joomla 4-6 features like mod_login, AJAX helpers, and HTML dialog.  Pure Joomla - no extensions needed.","author":{"@type":"Person","name":"Michael Richey","url":"https://www.richeyweb.com/contact-us","@id":"https://www.richeyweb.com/contact-us#person"},"datePublished":"2026-04-12T00:00:00+00:00","dateModified":"2026-04-12T00:00:00+00:00","about":["Joomla",{"@type":"Thing","name":"Joomla","sameAs":["https://en.wikipedia.org/wiki/Joomla","https://www.wikidata.org/wiki/Q13167","https://g.co/kg/m/07qb81"]},"Content management system",{"@type":"Thing","name":"Content management system","sameAs":["https://en.wikipedia.org/wiki/Content_management_system","https://www.wikidata.org/wiki/Q131093","https://g.co/kg/m/0k23c"]},"Front-end web development",{"@type":"Thing","name":"Front-end web development","sameAs":["https://en.wikipedia.org/wiki/Front-end_web_development","https://www.wikidata.org/wiki/Q4130556","https://g.co/kg/m/010gqt_p"]},"Authentication",{"@type":"Thing","name":"Authentication","sameAs":["https://en.wikipedia.org/wiki/Authentication","https://www.wikidata.org/wiki/Q212108","https://g.co/kg/m/0cw7p"]},"User interface design",{"@type":"Thing","name":"User interface design","sameAs":["https://en.wikipedia.org/wiki/User_interface_design","https://www.wikidata.org/wiki/Q135707","https://g.co/kg/m/06_275"]},"Modal window",{"@type":"Thing","name":"Modal window","sameAs":["https://en.wikipedia.org/wiki/Modal_window","https://www.wikidata.org/wiki/Q776657","https://g.co/kg/m/01j767"]}],"mentions":["JavaScript",{"@type":"Thing","name":"JavaScript","sameAs":["https://en.wikipedia.org/wiki/JavaScript","https://www.wikidata.org/wiki/Q2005","https://g.co/kg/m/02p97"]},"Ajax",{"@type":"Thing","name":"Ajax","sameAs":["https://en.wikipedia.org/wiki/Ajax_(programming)","https://www.wikidata.org/wiki/Q169527","https://g.co/kg/m/05gj6g"]},"HTML",{"@type":"Thing","name":"HTML","sameAs":["https://en.wikipedia.org/wiki/HTML","https://www.wikidata.org/wiki/Q8811","https://g.co/kg/m/03g20"]},"CSS",{"@type":"Thing","name":"CSS","sameAs":["https://en.wikipedia.org/wiki/CSS","https://www.wikidata.org/wiki/Q46441","https://g.co/kg/m/015tjh"]},"PHP",{"@type":"Thing","name":"PHP","sameAs":["https://en.wikipedia.org/wiki/PHP","https://www.wikidata.org/wiki/Q59","https://g.co/kg/m/060kv"]},"Web browser",{"@type":"Thing","name":"Web browser","sameAs":["https://en.wikipedia.org/wiki/Web_browser","https://www.wikidata.org/wiki/Q6368","https://g.co/kg/m/082hp"]},"HTML element",{"@type":"Thing","name":"HTML element","sameAs":["https://en.wikipedia.org/wiki/HTML_element","https://www.wikidata.org/wiki/Q179551","https://g.co/kg/m/01p484"]},"Dialog box",{"@type":"Thing","name":"Dialog box","sameAs":["https://en.wikipedia.org/wiki/Dialog_box","https://www.wikidata.org/wiki/Q86915","https://g.co/kg/m/01fvkl"]},"Session ID",{"@type":"Thing","name":"Session ID","sameAs":["https://en.wikipedia.org/wiki/Session_ID","https://www.wikidata.org/wiki/Q744575","https://g.co/kg/m/02763hx"]},"Single-page application",{"@type":"Thing","name":"Single-page application","sameAs":["https://en.wikipedia.org/wiki/Single-page_application","https://www.wikidata.org/wiki/Q1990286","https://g.co/kg/m/06ztvdn"]},"User experience design",{"@type":"Thing","name":"User experience design","sameAs":["https://en.wikipedia.org/wiki/User_experience_design","https://www.wikidata.org/wiki/Q11248500","https://g.co/kg/g/120_g8jl"]},"Open-source software",{"@type":"Thing","name":"Open-source software","sameAs":["https://en.wikipedia.org/wiki/Open-source_software","https://www.wikidata.org/wiki/Q1130645","https://g.co/kg/m/01pjyj"]},{"@type":"Article","@id":"https://www.richeyweb.com/test-article#article","url":"https://www.richeyweb.com/test-article","name":"Shader BG Test","headline":"Shader BG Test","author":{"@type":"Person","name":"Michael Richey","url":"https://www.richeyweb.com/contact-us","@id":"https://www.richeyweb.com/contact-us#person"}},{"@type":"Article","@id":"https://www.richeyweb.com/blog/hosting/cron-vs-joomla-lazy-scheduler-and-webcron#article","url":"https://www.richeyweb.com/blog/hosting/cron-vs-joomla-lazy-scheduler-and-webcron","name":"Cron vs Joomla Lazy Scheduler and WebCron","headline":"Cron vs Joomla Lazy Scheduler and WebCron","image":{"@type":"ImageObject","url":"https://www.richeyweb.com/images/articles/lazy-scheduler-and-web-cron/lazy-scheduler-and-web-cron.webp","contentUrl":"https://www.richeyweb.com/images/articles/lazy-scheduler-and-web-cron/lazy-scheduler-and-web-cron.webp","width":{"@type":"QuantitativeValue","value":888,"unitCode":"PX"},"height":{"@type":"QuantitativeValue","value":499,"unitCode":"PX"},"caption":"Cron vs Joomla Lazy Scheduler and WebCron"},"author":{"@type":"Person","name":"Michael Richey","url":"https://www.richeyweb.com/contact-us","@id":"https://www.richeyweb.com/contact-us#person"}},{"@type":"Article","@id":"https://www.richeyweb.com/joomla-techniques/youtube-rss-feed-gallery#article","url":"https://www.richeyweb.com/joomla-techniques/youtube-rss-feed-gallery","name":"YouTube RSS Feed Gallery","headline":"YouTube RSS Feed Gallery","image":{"@type":"ImageObject","url":"https://www.richeyweb.com/images/tutorialmemes/i-bet-hes-thinking-about-other-women.webp","contentUrl":"https://www.richeyweb.com/images/tutorialmemes/i-bet-hes-thinking-about-other-women.webp","width":{"@type":"QuantitativeValue","value":889,"unitCode":"PX"},"height":{"@type":"QuantitativeValue","value":500,"unitCode":"PX"},"caption":"YouTube RSS Feed Gallery"},"author":{"@type":"Person","name":"Michael Richey","url":"https://www.richeyweb.com/contact-us","@id":"https://www.richeyweb.com/contact-us#person"}},{"@type":"Article","@id":"https://www.richeyweb.com/blog/hosting/mastering-the-html-head-in-joomla#article","url":"https://www.richeyweb.com/blog/hosting/mastering-the-html-head-in-joomla","name":"Mastering the HTML head in Joomla","headline":"Mastering the HTML head in Joomla","image":{"@type":"ImageObject","url":"https://www.richeyweb.com/images/articles/metarobots/system-metarobots.webp","contentUrl":"https://www.richeyweb.com/images/articles/metarobots/system-metarobots.webp","width":{"@type":"QuantitativeValue","value":888,"unitCode":"PX"},"height":{"@type":"QuantitativeValue","value":499,"unitCode":"PX"},"caption":"Mastering the HTML head in Joomla"},"author":{"@type":"Person","name":"Michael Richey","url":"https://www.richeyweb.com/contact-us","@id":"https://www.richeyweb.com/contact-us#person"}},{"@type":"Article","@id":"https://www.richeyweb.com/blog/hosting/varnish-and-joomla#article","url":"https://www.richeyweb.com/blog/hosting/varnish-and-joomla","name":"Varnish and Joomla","headline":"Varnish and Joomla","image":{"@type":"ImageObject","url":"https://www.richeyweb.com/images/articles/varnish-nginx-joomla/varnish-and-joomla.webp","contentUrl":"https://www.richeyweb.com/images/articles/varnish-nginx-joomla/varnish-and-joomla.webp","width":{"@type":"QuantitativeValue","value":890,"unitCode":"PX"},"height":{"@type":"QuantitativeValue","value":500,"unitCode":"PX"},"caption":"Varnish and Joomla"},"author":{"@type":"Person","name":"Michael Richey","url":"https://www.richeyweb.com/contact-us","@id":"https://www.richeyweb.com/contact-us#person"}},{"@type":"Article","@id":"https://www.richeyweb.com/blog/development/new-for-2025#article","url":"https://www.richeyweb.com/blog/development/new-for-2025","name":"New for 2025","headline":"New for 2025","image":{"@type":"ImageObject","url":"https://www.richeyweb.com/images/articles/new-2025/joomla.svg","contentUrl":"https://www.richeyweb.com/images/articles/new-2025/joomla.svg","width":{"@type":"QuantitativeValue","value":800,"unitCode":"PX"},"height":{"@type":"QuantitativeValue","value":800,"unitCode":"PX"},"caption":"New for 2025"},"author":{"@type":"Person","name":"Michael Richey","url":"https://www.richeyweb.com/contact-us","@id":"https://www.richeyweb.com/contact-us#person"}},{"@type":"Article","@id":"https://www.richeyweb.com/blog/development/hashcash-free-privacy-first-captcha-for-joomla-in-2026#article","url":"https://www.richeyweb.com/blog/development/hashcash-free-privacy-first-captcha-for-joomla-in-2026","name":"HashCash: Free, Privacy-First CAPTCHA for Joomla in 2026","headline":"HashCash: Free, Privacy-First CAPTCHA for Joomla in 2026","image":{"@type":"ImageObject","url":"https://www.richeyweb.com/images/articles/hashcash-free-privacy-first-captcha-for-joomla-in-2026/trained-monkey-captcha.webp","contentUrl":"https://www.richeyweb.com/images/articles/hashcash-free-privacy-first-captcha-for-joomla-in-2026/trained-monkey-captcha.webp","width":{"@type":"QuantitativeValue","value":1360,"unitCode":"PX"},"height":{"@type":"QuantitativeValue","value":765,"unitCode":"PX"},"caption":"HashCash: Free, Privacy-First CAPTCHA for Joomla in 2026"},"author":{"@type":"Person","name":"Michael Richey","url":"https://www.richeyweb.com/contact-us","@id":"https://www.richeyweb.com/contact-us#person"}},{"@type":"Article","@id":"https://www.richeyweb.com/joomla-techniques/build-a-clean-joomla-header-search-popup-in-minutes-for-free#article","url":"https://www.richeyweb.com/joomla-techniques/build-a-clean-joomla-header-search-popup-in-minutes-for-free","name":"Build a Clean Joomla Header Search Popup in Minutes - For Free","headline":"Build a Clean Joomla Header Search Popup in Minutes - For Free","image":{"@type":"ImageObject","url":"https://www.richeyweb.com/images/articles/build-a-clean-joomla-header-search-popup-in-minutes-for-free/header-search-popup.webp","contentUrl":"https://www.richeyweb.com/images/articles/build-a-clean-joomla-header-search-popup-in-minutes-for-free/header-search-popup.webp","width":{"@type":"QuantitativeValue","value":651,"unitCode":"PX"},"height":{"@type":"QuantitativeValue","value":366,"unitCode":"PX"},"caption":"Build a Clean Joomla Header Search Popup in Minutes - For Free"},"author":{"@type":"Person","name":"Michael Richey","url":"https://www.richeyweb.com/contact-us","@id":"https://www.richeyweb.com/contact-us#person"}}],"@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#article","isPartOf":{"@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#webpage"},"publisher":{"@id":"https://www.richeyweb.com/#organization"},"citation":[{"@type":"CreativeWork","@id":"https://manual.joomla.org/docs/4.4/general-concepts/javascript/com-ajax/#creativework","url":"https://manual.joomla.org/docs/4.4/general-concepts/javascript/com-ajax/"},{"@type":"CreativeWork","@id":"https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog#creativework","url":"https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog"},{"@type":"CreativeWork","@id":"index.php?option=com_ajax&amp;template=cassiopeia&amp;method=loginForm&amp;format=html#creativework","url":"index.php?option=com_ajax&amp;template=cassiopeia&amp;method=loginForm&amp;format=html"}],"keywords":"login popup, Joomla, native login popup, mod_login, AJAX template helper, login module, com_ajax, helper.php, user.js, dialog element, ModuleHelper, Joomla 4, Joomla 5, Joomla 6, child template, menu item, System Links, Link CSS Style, session token, JavaScript, no-JavaScript fallback, template helper, post-login behavior, login form, show_login_form, greeting, renderModule, fetch, showModal, Joomla behaviors, custom CSS","articleSection":"Joomla Techniques","url":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla","hasPart":[{"@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#articleindex-toc-step-1-create-the-menu-item_2_1"},{"@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#articleindex-toc-step-2-create-the-template-helper-helper-php_2_2"},{"@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#articleindex-toc-step-3-add-the-javascript_2_3"},{"@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#articleindex-toc-login-popup-final-touches_2_4"},{"@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#articleindex-toc-official-documentation_2_5"},{"@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#articleindex-toc-why-this-approach-wins_2_6"},{"@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#articleindex-toc-login-popup-demo-absolutely_2_7"},{"@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#faqpage"}]},{"@type":"FAQPage","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#faqpage","url":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla","isPartOf":{"@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#article"},"mainEntityOfPage":{"@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#webpage"},"mainEntity":[{"@type":"Question","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#question-0","name":"Does this work with Joomla's existing login module settings?","acceptedAnswer":{"@type":"Answer","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#answer-0","text":"Yes. The popup loads your existing mod_login module exactly as configured — including post-login redirects, greeting settings, and any other parameters you've set. Nothing is overridden except presentation.","citation":{"@type":"CreativeWork","url":"https://docs.joomla.org/Help5.x:Site_Modules:_Login/en","name":"Help5.x:Site Modules: Login"}}},{"@type":"Question","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#question-1","name":"What happens if JavaScript is disabled?","acceptedAnswer":{"@type":"Answer","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#answer-1","text":"The menu item links directly to a fully functional login page. Visitors without JavaScript get a normal login experience — no broken UI, no dead links. The popup is a progressive enhancement, not a dependency.","citation":{"@type":"CreativeWork","url":"https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement","name":"MDN Web Docs — Progressive Enhancement"}}},{"@type":"Question","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#question-2","name":"What is com_ajax and why is it used here?","acceptedAnswer":{"@type":"Answer","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#answer-2","text":"com_ajax is a Joomla core component that provides a standardized way to make AJAX requests to modules, plugins, and templates without building a custom component. It's used here to load the login form into the popup without a full page reload.","citation":{"@type":"CreativeWork","url":"https://manual.joomla.org/docs/4.4/general-concepts/javascript/com-ajax/","name":"Using com_ajax for Modules, Plugins and Templates"}}},{"@type":"Question","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#question-3","name":"Why use the HTML dialog element instead of a custom modal?","acceptedAnswer":{"@type":"Answer","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#answer-3","text":"The native  element is built into modern browsers and handles accessibility, focus trapping, keyboard dismissal, and backdrop rendering automatically — without a single line of library code. It's the right tool for this job in 2025 and beyond.","citation":{"@type":"CreativeWork","url":"https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog","name":"dialog: The Dialog element"}}},{"@type":"Question","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#question-4","name":"Does this require a child template?","acceptedAnswer":{"@type":"Answer","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#answer-4","text":"Strongly recommended but not strictly required. Using a child template ensures that your helper.php file survives Joomla template updates without being overwritten. Modifying a parent template directly risks losing your changes on the next update.","citation":{"@type":"CreativeWork","url":"https://docs.joomla.org/J4.x:Child_Templates/en","name":"J4.x:Child Templates"}}},{"@type":"Question","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#question-5","name":"Will this work with third-party login plugins like social login extensions?","acceptedAnswer":{"@type":"Answer","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#answer-5","text":"If your social login extension integrates with mod_login and renders inside the standard module output, it will appear in the popup. Extensions that redirect to external OAuth flows will follow their normal behavior after the popup opens.","citation":{"@type":"CreativeWork","url":"https://docs.joomla.org/J4.x:Creating_an_Authentication_Plugin_for_Joomla","name":"J4.x:Creating an Authentication Plugin for Joomla"}}},{"@type":"Question","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#question-6","name":"Is this approach secure?","acceptedAnswer":{"@type":"Answer","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#answer-6","text":"Yes. The login form is rendered by Joomla's own mod_login module and submitted through Joomla's standard authentication system. The CSRF token, session handling, and all security mechanisms remain fully intact. No authentication logic is reimplemented.","citation":{"@type":"CreativeWork","url":"https://docs.joomla.org/How_to_add_CSRF_anti-spoofing_to_forms","name":"How to add CSRF anti-spoofing to forms"}}},{"@type":"Question","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#question-7","name":"Does the closedby=\"any\" attribute work in all browsers?","acceptedAnswer":{"@type":"Answer","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#answer-7","text":"closedby=\"any\" is a recent addition to the HTML  specification and is supported in modern browsers. In browsers that don't yet support it, the dialog still closes via the × button or the Escape key — the click-outside behavior degrades gracefully. ","citation":{"@type":"CreativeWork","url":"https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/closedBy","name":"MDN Web Docs — HTMLDialogElement: closedBy property"}}},{"@type":"Question","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#question-8","name":"Can I style the popup to match my template?","acceptedAnswer":{"@type":"Answer","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#answer-8","text":"Yes. The popup wrapper carries the class joomla-native-login-popup and the dialog element can be targeted directly in your template's user.css. All inline styles in the JavaScript are intentional defaults — they're fully overridable with standard CSS specificity.","citation":{"@type":"CreativeWork","url":"https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Cascade/Specificity","name":"MDN Web Docs — CSS Specificity"}}},{"@type":"Question","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#question-9","name":"Does this work on cached pages?","acceptedAnswer":{"@type":"Answer","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#answer-9","text":"The session token timeout handler addresses the most common caching issue — if the page has been cached and the login token has expired, the popup will alert the user rather than silently failing. For heavily cached sites, ensure mod_login is excluded from page caching.","citation":{"@type":"CreativeWork","url":"https://docs.joomla.org/Cache","name":"Joomla! Documentation — Cache"}}}]},{"@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#articleindex","@type":"ItemList","name":"Build a Native Login Popup Using Only Core Joomla","numberOfItems":7,"itemListElement":[{"@type":"ListItem","position":1,"item":{"@type":"WPHeader","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#articleindex-toc-step-1-create-the-menu-item_2_1","name":"Step 1: Create the Menu Item","url":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#toc-step-1-create-the-menu-item_2_1"}},{"@type":"ListItem","position":2,"item":{"@type":"WPHeader","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#articleindex-toc-step-2-create-the-template-helper-helper-php_2_2","name":"Step 2: Create the Template Helper (helper.php)","url":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#toc-step-2-create-the-template-helper-helper-php_2_2"}},{"@type":"ListItem","position":3,"item":{"@type":"WPHeader","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#articleindex-toc-step-3-add-the-javascript_2_3","name":"Step 3: Add the JavaScript","url":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#toc-step-3-add-the-javascript_2_3"}},{"@type":"ListItem","position":4,"item":{"@type":"WPHeader","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#articleindex-toc-login-popup-final-touches_2_4","name":"Login Popup Final Touches","url":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#toc-login-popup-final-touches_2_4"}},{"@type":"ListItem","position":5,"item":{"@type":"WPHeader","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#articleindex-toc-official-documentation_2_5","name":"Official Documentation","url":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#toc-official-documentation_2_5"}},{"@type":"ListItem","position":6,"item":{"@type":"WPHeader","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#articleindex-toc-why-this-approach-wins_2_6","name":"Why This Approach Wins","url":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#toc-why-this-approach-wins_2_6"}},{"@type":"ListItem","position":7,"item":{"@type":"WPHeader","@id":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#articleindex-toc-login-popup-demo-absolutely_2_7","name":"Login Popup Demo? Absolutely!","url":"https://www.richeyweb.com/joomla-techniques/build-a-native-login-popup-using-only-core-joomla#toc-login-popup-demo-absolutely_2_7"}}]}]}
```
