[Solved] Keeping current class ('w--current') when using .htaccess (to remove .html extension)

I thought I’d share my findings to help others experiencing the same issues.

For context, I’ve exported one of my clients websites and have used a .htaccess file to remove the .html extension from the browser url, e.g. “https://www.website.com/about.html” now appears as “https://www.website.com/about”. All works nicely :grinning:

.htaccess file

RewriteEngine On
RewriteRule ^index\.html$ / [R=301,L]
RewriteRule ^(.*)/index\.html$ /$1/ [R=301,L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.+)$ $1.html [L,QSA]

#301 from example.com/page.html to example.com/page

RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\.html\ HTTP/
RewriteRule ^(.*)\.html$ /$1 [R=301,L]

However, a consequence of removing the .html extension is the Webflow Javascript can no longer match the page url with any matching links (as the link urls still refer to the .html version). This means that any links that should be using w--current class will not have it applied (the homepage being the exception) :pensive:

To get around this, I used a custom piece of Javascript which would add the w--current class as expected – regardless of whether the .html extension was present or not. This should have been the end of the story, but there was another challenge ahead…

Custom Javascript to add class to current page links

function getBaseName(url) {
    if (!url || (url && url.length === 0)) {
        return "";
    }
    var index = url.lastIndexOf("/") + 1;
    var filenameWithExtension = url.substr(index);
    var basename = filenameWithExtension.split(/[.?&#]+/)[0];

    // Handle '/mypage/' type paths
    if (basename.length === 0) {
        url = url.substr(0, index - 1);
        basename = getBaseName(url);
    }
    return basename ? basename : "";
}

var url = window.location.href;
var url2 = getBaseName(url);

$('a[href^="' + url2 + '"]').addClass('w-active');

Basically it appears that the Webflow Javascript also removes any trace of thew--current class (unless it added it). This means when I added the class via my custom Javascript, the Webflow Javascript removed it :cry:

My workaround was to dynamically copy the css styles from the .nav-link.w--current class and then add them to a new class: w-active. Bit hacky I know, but seems to work :crossed_fingers:

Custom Javascript to copy .w–current css styles to w-active

(function($){
    $.fn.getStyleObject = function(){
        var dom = this.get(0);
        var style;
        var returns = {};
        if(window.getComputedStyle){
            var camelize = function(a,b){
                return b.toUpperCase();
            };
            style = window.getComputedStyle(dom, null);
            for(var i = 0, l = style.length; i < l; i++){
                var prop = style[i];
                var camel = prop.replace(/\-([a-z])/g, camelize);
                var val = style.getPropertyValue(prop);
                returns[camel] = val;
            };
            return returns;
        };
        if(style = dom.currentStyle){
            for(var prop in style){
                returns[prop] = style[prop];
            };
            return returns;
        };
        return this.css();
    }
})(jQuery);
$.fn.copyCSS = function(source){
  var styles = $(source).getStyleObject();
  this.css(styles);
}

// Copy the styles from the existing class to the new class

$('.nav-link.w--current').copyCSS('.w-active');

Hope this helps others :+1:

3 Likes

There is code in the base webflow.js file that adds and removes that class to menu items. I suspect you are experiencing a collision.

Also useful for .htaccess redirects:

1 Like

Thank you so much for the solution for this! It was driving me crazy. Webflow if you see this PLEASE add this to the backlog! :slight_smile:

1 Like

Can you please explain what should I copy in the code and what should I change? I don’t know nothing about javascript and changing only the nav-link class don’t worked :frowning:

I’m sure that I’m doing something wrong.