In Firefox the M1 Porto demo site has some JS Warnings which may be the culprit. A return is in the following method as well as subsequent code which could explain the difficult in finding the elements absolute position to scroll to on validation errors.

    /*
     * Different ways to find element's absolute position
     */
    Calendar.getAbsolutePos = function(element) {
    
        var res = new Object();
        res.x = 0; res.y = 0;
    
        // variant 1 (working best, copy-paste from prototype library)
        do {
            res.x += element.offsetLeft || 0;
            res.y += element.offsetTop  || 0;
            element = element.offsetParent;
            if (element) {
                if (element.tagName.toUpperCase() == 'BODY') break;
                var p = Calendar.getStyle(element, 'position');
                if ((p !== 'static') && (p !== 'relative')) break;
            }
        } while (element);
    
        return res; // <-- B00MER NOTE: this shouldn't be returning res here, return only AT end of method or some code can become unreachable by the browsers DOM implemenation.
    
        // variant 2 (good solution, but lost in IE8)
        if (element !== null) {
            res.x = element.offsetLeft;
            res.y = element.offsetTop;
    
            var offsetParent = element.offsetParent;
            var parentNode = element.parentNode;
    
            while (offsetParent !== null) {
                res.x += offsetParent.offsetLeft;
                res.y += offsetParent.offsetTop;
    
                if (offsetParent != document.body && offsetParent != document.documentElement) {
                    res.x -= offsetParent.scrollLeft;
                    res.y -= offsetParent.scrollTop;
                }
                //next lines are necessary to support FireFox problem with offsetParent
                if (Calendar.is_gecko) {
                    while (offsetParent != parentNode && parentNode !== null) {
                        res.x -= parentNode.scrollLeft;
                        res.y -= parentNode.scrollTop;
                        parentNode = parentNode.parentNode;
                    }
                }
                parentNode = offsetParent.parentNode;
                offsetParent = offsetParent.offsetParent;
            }
        }
        return res;
    
        // variant 2 (not working)
    
    //    var SL = 0, ST = 0;
    //    var is_div = /^div$/i.test(el.tagName);
    //    if (is_div && el.scrollLeft)
    //        SL = el.scrollLeft;
    //    if (is_div && el.scrollTop)
    //        ST = el.scrollTop;
    //    var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST };
    //    if (el.offsetParent) {
    //        var tmp = this.getAbsolutePos(el.offsetParent);
    //        r.x += tmp.x;
    //        r.y += tmp.y;
    //    }
    //    return r;
    };

**SEE INLINE COMMENT NOTE IN ABOVE CODE.**

More details as to what could possibly be band-aids for other lesser browser version support that is breaking others.

- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Stmt_after_return

> What went wrong?
> 
> Unreachable code after a return statement might occur in these
> situations:
> 
>     When using an expression after a return statement, or
>     when using a semicolon-less return statement but including an expression directly after.
> 
> When an expression exists after a valid return statement, a warning is
> given to indicate that the code after the return statement is
> unreachable, meaning it can never be run.
> 
> Why should I have semicolons after return statements? In the case of
> semicolon-less return statements, it can be unclear whether the
> developer intended to return the statement on the following line, or
> to stop execution and return. The warning indicates that there is
> ambiguity in the way the return statement is written.
> 
> Warnings will not be shown for semicolon-less returns if these
> statements follow it:
> 
>     throw
>     break
>     var
>     function

Other code unreachable as well:

    reloadPrice: function(){
        var price    = 0;
        var oldPrice = 0;
        for(var i=this.settings.length-1;i>=0;i--){
            var selected = this.settings[i].options[this.settings[i].selectedIndex];
            if(selected.config){
                price    += parseFloat(selected.config.price);
                oldPrice += parseFloat(selected.config.oldPrice);
            }
        }
    
        optionsPrice.changePrice('config', {'price': price, 'oldPrice': oldPrice});
        optionsPrice.reload();
    
        return price;
    
        if($('product-price-'+this.config.productId)){
            $('product-price-'+this.config.productId).innerHTML = price;
        }
        this.reloadOldPrice();
    },

Also, it may help if known Browsers with issues & if any without? Ultimately best approach is to get support from the Porto authors to see if there is a fix and/or if others experience similar issues.

Hope this helps!