Improve rendering performance
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/jquery/jquery-scout-selectors.js b/org.eclipse.scout.rt.ui.html/src/main/js/jquery/jquery-scout-selectors.js
index 7eef68b..a379fa9 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/jquery/jquery-scout-selectors.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/jquery/jquery-scout-selectors.js
@@ -14,19 +14,20 @@
  */
 function focusable(element, isTabIndexNotNaN) {
   var nodeName = element.nodeName.toLowerCase();
+  var $element = $(element);
   return (/input|select|textarea|button|object/.test(nodeName) ?
       !element.disabled :
       'a' === nodeName ?
       element.href || isTabIndexNotNaN :
       isTabIndexNotNaN) &&
     // the element and all of its ancestors must be visible
-    visible(element);
+    $element.isVisible() && $element.isEveryParentVisible();
 }
 
 function visible(element) {
   return $.expr.filters.visible(element) &&
     !$(element).parents().addBack().filter(function() {
-      return $.css(this, 'visibility') === 'hidden';
+      return !$(this).isVisible();//$.css(this, 'visibility') === 'hidden';
     }).length;
 }
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/jquery/jquery-scout.js b/org.eclipse.scout.rt.ui.html/src/main/js/jquery/jquery-scout.js
index 5cda72d..a730982 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/jquery/jquery-scout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/jquery/jquery-scout.js
@@ -914,7 +914,7 @@
 };
 
 $.fn.isVisible = function() {
-  return elemVisible(this[0]);
+  return !this.hasClass('hidden');
 };
 
 $.fn.isEveryParentVisible = function() {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/focus/FocusContext.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/focus/FocusContext.js
index a05680b..752e24a 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/focus/FocusContext.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/focus/FocusContext.js
@@ -207,7 +207,7 @@
   var $elementToFocus = $(elementToFocus);
 
   // Focus the requested element
-  $elementToFocus.focus();
+//  $elementToFocus.focus();
 
   $.log.isDebugEnabled() && $.log.debug('Focus set to ' + scout.graphics.debugOutput(elementToFocus));
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/GroupBoxResponsiveHandler.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/GroupBoxResponsiveHandler.js
index 2b5cc1f..728736c 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/GroupBoxResponsiveHandler.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/GroupBoxResponsiveHandler.js
@@ -144,8 +144,13 @@
   }
 
   // suppress a revalidate of the layout tree, since setLabelPosition would trigger it.
+  var htmlParent;
   if (widget.htmlComp) {
     widget.htmlComp.suppressInvalidate = true;
+    htmlParent = widget.htmlComp.getParent();
+    if (htmlParent) {
+      htmlParent.suppressInvalidate = true;
+    }
   }
 
   scout.GroupBoxResponsiveHandler.parent.prototype._transformWidget.call(this, widget);
@@ -153,6 +158,9 @@
   if (widget.htmlComp) {
     widget.htmlComp.suppressInvalidate = false;
   }
+  if (htmlParent) {
+    htmlParent.suppressInvalidate = false;
+  }
 };
 
 /* --- TRANSFORMATIONS ------------------------------------------------------------- */
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormField.less b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormField.less
index 9433445..881a8c1 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormField.less
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormField.less
@@ -74,6 +74,7 @@
   & > .mandatory-indicator {
     position: absolute;
     visibility: hidden;
+    width: @mandatory-indicator-width;
 
     &::before {
       content: '*';
@@ -92,6 +93,7 @@
   & > .status {
     position: absolute;
     margin-left: @field-status-margin-left;
+    width: @field-status-width;
     height: @status-font-icon-size; /* Same as font-size of status icon */
 
     #scout.status();
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormFieldLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormFieldLayout.js
index d167d01..5417569 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormFieldLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormFieldLayout.js
@@ -64,53 +64,50 @@
       if (formField.$label.hasClass('empty')) {
         labelWidth = 0;
       } else {
-        labelWidth = scout.graphics.prefSize(formField.$label).width;
+        labelWidth = 32;//scout.graphics.prefSize(formField.$label).width;
       }
     }
     if (scout.isOneOf(formField.labelPosition, scout.FormField.LabelPosition.DEFAULT, scout.FormField.LabelPosition.LEFT)) {
-      scout.graphics.setBounds(formField.$label, left, top, labelWidth, this.rowHeight);
+//      scout.graphics.setBounds(formField.$label, left, top, labelWidth, this.rowHeight);
       left += labelWidth + formField.$label.cssMarginX();
     } else if (formField.labelPosition === scout.FormField.LabelPosition.TOP) {
-      var labelHeight = scout.graphics.prefSize(formField.$label).height;
+      var labelHeight = 32;//scout.graphics.prefSize(formField.$label).height;
       // prefSize rounds the value -> ensure label height is set to that value to prevent gaps between container and label.
       // In addition, this also ensures that the correct height is set when changing the label position from left to top
-      formField.$label.cssHeight(labelHeight);
+//      formField.$label.cssHeight(labelHeight);
       top += labelHeight + formField.$label.cssMarginY();
       labelHasFieldWidth = true;
     }
   }
   if (formField.$mandatory && formField.$mandatory.isVisible()) {
-    formField.$mandatory
-      .cssTop(top)
-      .cssLeft(left)
-      .cssWidth(this.mandatoryIndicatorWidth);
-    left += formField.$mandatory.outerWidth(true);
+//    formField.$mandatory
+//      .cssTop(top)
+//      .cssLeft(left);
+    left += this.mandatoryIndicatorWidth + formField.$mandatory.cssMarginX();//formField.$mandatory.outerWidth(true);
   }
   if (this._isStatusVisible()) {
-    formField.$status
-      .cssWidth(statusWidth);
     // If both status and label position is "top", pull status up (without margin on the right side)
     if (formField.statusPosition === scout.FormField.StatusPosition.TOP && labelHasFieldWidth) {
-      var statusHeight = scout.graphics.prefSize(formField.$status, {
-        useCssSize: true
-      }).height;
+      var statusHeight = 32;//scout.graphics.prefSize(formField.$status, {
+//        useCssSize: true
+//      }).height;
       // Vertically center status with label
       var statusTop = containerPadding.top + formField.$label.cssPaddingTop() + (formField.$label.height() / 2) - (statusHeight / 2);
-      formField.$status
-        .cssTop(statusTop)
-        .cssRight(right + formField.$label.cssMarginRight())
-        .cssHeight(statusHeight)
-        .cssLineHeight(null);
+//      formField.$status
+//        .cssTop(statusTop)
+//        .cssRight(right + formField.$label.cssMarginRight())
+//        .cssHeight(statusHeight)
+//        .cssLineHeight(null);
       // Add padding to label to prevent overlay of text and status icon
       var w = scout.graphics.size(formField.$status, true).width;
-      formField.$label.cssPaddingRight(w);
+//      formField.$label.cssPaddingRight(w);
     } else {
       // Default status position
-      formField.$status
-        .cssTop(top)
-        .cssRight(right)
-        .cssHeight(this.rowHeight)
-        .cssLineHeight(this.rowHeight);
+//      formField.$status
+//        .cssTop(top)
+//        .cssRight(right)
+//        .cssHeight(this.rowHeight)
+//        .cssLineHeight(this.rowHeight);
       right += statusWidth + formField.$status.cssMarginX();
     }
   }
@@ -137,19 +134,19 @@
     }
     htmlField = scout.HtmlComponent.optGet(formField.$fieldContainer);
     if (htmlField) {
-      htmlField.setBounds(fieldBounds);
+//      htmlField.setBounds(fieldBounds);
     } else {
-      scout.graphics.setBounds(formField.$fieldContainer, fieldBounds);
+//      scout.graphics.setBounds(formField.$fieldContainer, fieldBounds);
     }
-    formField.$field.toggleClass('compact', fieldBounds.width <= scout.FormFieldLayout.MIN_FIELD_WIDTH);
-    formField.$container.toggleClass('compact', fieldBounds.width <= scout.FormFieldLayout.MIN_FIELD_WIDTH);
+//    formField.$field.toggleClass('compact', fieldBounds.width <= scout.FormFieldLayout.MIN_FIELD_WIDTH);
+//    formField.$container.toggleClass('compact', fieldBounds.width <= scout.FormFieldLayout.MIN_FIELD_WIDTH);
 
     if (labelHasFieldWidth) {
       var fieldWidth = fieldSize.add(fieldMargins).width - formField.$label.cssMarginX();
       if (formField.$mandatory && formField.$mandatory.isVisible()) {
         fieldWidth += formField.$mandatory.outerWidth(true);
       }
-      formField.$label.cssWidth(fieldWidth);
+//      formField.$label.cssWidth(fieldWidth);
     }
   }
 
@@ -208,11 +205,11 @@
     var scrollVertical = overflowY === 'scroll' || overflowY === 'auto' && (elem.scrollHeight - elem.clientHeight) > 0;
     var scrollbarSize = scout.device.scrollbarWidth;
 
-    $overlay
-      .css('top', pos.top)
-      .css('left', pos.left)
-      .width($field.width() + padding.horizontal() - (scrollVertical ? scrollbarSize : 0))
-      .height($field.height() + padding.vertical() - (scrollHorizontal ? scrollbarSize : 0));
+//    $overlay
+//      .css('top', pos.top)
+//      .css('left', pos.left)
+//      .width($field.width() + padding.horizontal() - (scrollVertical ? scrollbarSize : 0))
+//      .height($field.height() + padding.vertical() - (scrollHorizontal ? scrollbarSize : 0));
 
   }
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/LookupBox.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/LookupBox.js
index a62c29a..b8ca07e 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/LookupBox.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/LookupBox.js
@@ -35,6 +35,7 @@
   if (this.filterBox) {
     this.filterBox.enabledComputed = true; // filter is always enabled
     this.filterBox.recomputeEnabled(true);
+    this.filterBox.on('propertyChange', this._onFilterBoxPropertyChange.bind(this));
   }
 };
 
@@ -60,12 +61,13 @@
   this._renderStructure();
   this.$field.addDeviceClass();
   this.$field.addClass('structure');
-  if (this.filterBox) {
-    this._renderFilterBox();
-  }
+  this._renderFilterBox();
 };
 
 scout.LookupBox.prototype._renderFilterBox = function() {
+  if (!this.filterBox || !this.filterBox.visible || this.filterBox.rendered) {
+    return;
+  }
   this.filterBox.render(this.$fieldContainer);
 };
 
@@ -230,3 +232,16 @@
 scout.LookupBox.prototype._clear = function() {
   this.setValue(null);
 };
+
+scout.LookupBox.prototype._onFilterBoxPropertyChange = function(event) {
+  if (event.propertyName === 'visible') {
+    if (!this.rendered) {
+      return;
+    }
+    if (this.filterBox.visible) {
+      this._renderFilterBox();
+    } else {
+      this.filterBox.remove();
+    }
+  }
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/LookupBoxLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/LookupBoxLayout.js
index 666f082..7d5a611 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/LookupBoxLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/LookupBoxLayout.js
@@ -22,7 +22,7 @@
     height = size.height,
     filterBoxHeight;
 
-  if (this.filterBox && this.filterBox.rendered && this.filterBox.$container.isVisible()) {
+  if (this.filterBox && this.filterBox.rendered) {
     filterBoxHeight = scout.HtmlComponent.get(this.filterBox.$container).prefSize().height;
     height -= filterBoxHeight;
   }
@@ -31,7 +31,7 @@
   var htmlStructure = scout.HtmlComponent.get(this.structure.$container);
   htmlStructure.setSize(new scout.Dimension(size.width, height));
 
-  if (this.filterBox && this.filterBox.rendered && this.filterBox.$container.isVisible()) {
+  if (this.filterBox && this.filterBox.rendered) {
     var htmlFilterBox = scout.HtmlComponent.get(this.filterBox.$container);
     htmlFilterBox.setSize(new scout.Dimension(size.width, filterBoxHeight));
   }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/listbox/ListBox.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/listbox/ListBox.js
index f374493..3725fe4 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/listbox/ListBox.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/listbox/ListBox.js
@@ -42,10 +42,8 @@
 
 scout.ListBox.prototype._renderStructure = function() {
   this.table.render(this.$fieldContainer);
+  this.table.htmlComp.pixelBasedSizing = true;
   this.addField(this.table.$container);
-  if (this.filterBox) {
-    this.table.htmlComp.pixelBasedSizing = true;
-  }
 };
 
 scout.ListBox.prototype._onTableRowsChecked = function(event) {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/treebox/TreeBox.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/treebox/TreeBox.js
index e8206aa..4fb98cd 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/treebox/TreeBox.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/treebox/TreeBox.js
@@ -45,10 +45,8 @@
 
 scout.TreeBox.prototype._renderStructure = function($fieldContainer) {
   this.tree.render(this.$fieldContainer);
+  this.tree.htmlComp.pixelBasedSizing = true;
   this.addField(this.tree.$container);
-  if (this.filterBox) {
-    this.tree.htmlComp.pixelBasedSizing = true;
-  }
 };
 
 scout.TreeBox.prototype._onTreeNodesChecked = function(event) {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/treebox/TreeBoxLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/treebox/TreeBoxLayout.js
index 62369c5..d0defd4 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/treebox/TreeBoxLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/treebox/TreeBoxLayout.js
@@ -11,5 +11,4 @@
 scout.TreeBoxLayout = function(treeBox, tree, filterBox) {
   scout.TreeBoxLayout.parent.call(this, treeBox, tree, filterBox);
 };
-
 scout.inherits(scout.TreeBoxLayout, scout.LookupBoxLayout);
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/HtmlComponent.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/HtmlComponent.js
index 0b54f35..4497d2f 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/HtmlComponent.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/HtmlComponent.js
@@ -91,7 +91,7 @@
  */
 scout.HtmlComponent.prototype.availableSize = function(options) {
   options = options || {};
-  var size = this.size({
+  var size = this.sizeCached || this.size({
     exact: options.exact
   });
 
@@ -116,6 +116,7 @@
 scout.HtmlComponent.prototype.invalidateLayout = function(htmlSource) {
   this.valid = false;
   this.prefSizeCached = {};
+  this.sizeCached = null;
   if (this.layout) {
     this.layout.invalidate(htmlSource);
   }
@@ -146,9 +147,10 @@
     this.layout.layout(this.$comp);
     this.layouting = false;
     this.layouted = true;
-    // Save size for later use (necessary if pixelBasedSizing is set to false)
-    this.sizeCached = this.size();
     this.valid = true;
+    if (!this.sizeCached) {
+      this.sizeCached = this.size();
+    }
   }
   return true;
 };
@@ -344,6 +346,8 @@
   }
   if (this.pixelBasedSizing) {
     scout.graphics.setSize(this.$comp, size);
+    // Save size for later use (necessary if pixelBasedSizing is set to false)
+    this.sizeCached = size;
   }
   this.validateLayout();
 };
@@ -386,6 +390,7 @@
     this.invalidateLayout();
   }
   scout.graphics.setBounds(this.$comp, bounds);
+  this.sizeCached = bounds.dimension();
   this.validateLayout();
 };
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/graphics.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/graphics.js
index fd39065..f7edf7e 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/graphics.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/graphics.js
@@ -53,7 +53,7 @@
   prefSize: function($elem, options) {
     // Return 0/0 if element is not displayed (display: none).
     // We don't use isVisible by purpose because isVisible returns false for elements with visibility: hidden which is wrong here (we would like to be able to measure hidden elements)
-    if (!$elem[0] || $elem.isDisplayNone()) {
+    if (!$elem[0] || !$elem.isVisible()) {
       return new scout.Dimension(0, 0);
     }
 
@@ -179,7 +179,7 @@
    *          of an object, the value is automatically converted to the option "includeMargin".
    */
   size: function($elem, options) {
-    if (!$elem[0] || $elem.isDisplayNone()) {
+    if (!$elem[0] || !$elem.isVisible()) {
       return new scout.Dimension(0, 0);
     }
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/scrollbar/scrollbars.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/scrollbar/scrollbars.js
index d17ff5a..0cf8ef5 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/scrollbar/scrollbars.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/scrollbar/scrollbars.js
@@ -142,15 +142,15 @@
 
     // Container with JS scrollbars must have either relative or absolute position
     // otherwise we cannot determine the correct dimension of the scrollbars
-    var cssPosition = $container.css('position');
-    if (!scout.isOneOf(cssPosition, 'relative', 'absolute')) {
-      $container.css('position', 'relative');
-    }
+//    var cssPosition = $container.css('position');
+//    if (!scout.isOneOf(cssPosition, 'relative', 'absolute')) {
+//      $container.css('position', 'relative');
+//    }
 
-    scrollbars.forEach(function(scrollbar) {
-      scrollbar.render($container);
-      scrollbar.update();
-    });
+//    scrollbars.forEach(function(scrollbar) {
+//      scrollbar.render($container);
+//      scrollbar.update();
+//    });
   },
 
   /**
@@ -213,16 +213,16 @@
 
   _update: function(scrollbars) {
     // Reset the scrollbars first to make sure they don't extend the scrollSize
-    scrollbars.forEach(function(scrollbar) {
-      if (scrollbar.rendered) {
-        scrollbar.reset();
-      }
-    });
-    scrollbars.forEach(function(scrollbar) {
-      if (scrollbar.rendered) {
-        scrollbar.update();
-      }
-    });
+//    scrollbars.forEach(function(scrollbar) {
+//      if (scrollbar.rendered) {
+//        scrollbar.reset();
+//      }
+//    });
+//    scrollbars.forEach(function(scrollbar) {
+//      if (scrollbar.rendered) {
+//        scrollbar.update();
+//      }
+//    });
   },
 
   /**
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/Table.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/Table.js
index e49c570..b392b44 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/Table.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/Table.js
@@ -1401,11 +1401,12 @@
 };
 
 scout.Table.prototype._calculateRowBorderWidth = function() {
-  var $tableRowDummy = this.$data.appendDiv('table-row');
-  this.rowBorderLeftWidth = $tableRowDummy.cssBorderLeftWidth();
-  this.rowBorderRightWidth = $tableRowDummy.cssBorderRightWidth();
-  this.rowBorderWidth = this.rowBorderLeftWidth + this.rowBorderRightWidth;
-  $tableRowDummy.remove();
+//  var $tableRowDummy = this.$data.appendDiv('table-row');
+//  this.rowBorderLeftWidth = $tableRowDummy.cssBorderLeftWidth();
+//  this.rowBorderRightWidth = $tableRowDummy.cssBorderRightWidth();
+//  this.rowBorderWidth = this.rowBorderLeftWidth + this.rowBorderRightWidth;
+//  $tableRowDummy.remove();
+  return 1;
 };
 
 scout.Table.prototype._updateRowWidth = function() {
@@ -1415,15 +1416,17 @@
 };
 
 scout.Table.prototype._updateRowHeight = function() {
-  var $emptyRow = this.$data.appendDiv('table-row');
-  var $emptyAggrRow = this.$data.appendDiv('table-aggregate-row');
-
-  $emptyRow.appendDiv('table-cell').html('&nbsp;');
-  $emptyAggrRow.appendDiv('table-cell').html('&nbsp;');
-  this.rowHeight = $emptyRow.outerHeight(true);
-  this.aggregateRowHeight = $emptyAggrRow.outerHeight(true);
-  $emptyRow.remove();
-  $emptyAggrRow.remove();
+//  var $emptyRow = this.$data.appendDiv('table-row');
+//  var $emptyAggrRow = this.$data.appendDiv('table-aggregate-row');
+//
+//  $emptyRow.appendDiv('table-cell').html('&nbsp;');
+//  $emptyAggrRow.appendDiv('table-cell').html('&nbsp;');
+//  this.rowHeight = $emptyRow.outerHeight(true);
+//  this.aggregateRowHeight = $emptyAggrRow.outerHeight(true);
+//  $emptyRow.remove();
+//  $emptyAggrRow.remove();
+  this.rowHeight = 30;
+  this.aggregateRowHeight = 30;
 };
 
 /**
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/Tree.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/Tree.js
index 33a64bf..b9e301c 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/Tree.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/Tree.js
@@ -530,16 +530,16 @@
 };
 
 scout.Tree.prototype.ensureRangeVisible = function(range) {
-  var nodes = this.visibleNodesFlat,
-    numNodesRendered = 0;
+  var nodes = this.visibleNodesFlat;
+  var nodesToInsert = [];
   for (var r = range.from; r < range.to; r++) {
     var node = nodes[r];
     if (!node.attached) {
-      this._insertNodeInDOM(node);
-      numNodesRendered++;
+      nodesToInsert.push(node);
     }
   }
-  return numNodesRendered;
+  this._insertNodesInDOM(nodesToInsert);
+  return nodesToInsert.length;
 };
 
 scout.Tree.prototype._renderFiller = function() {
@@ -724,23 +724,24 @@
   return this.visibleNodesFlat.slice(this.viewRangeRendered.from, this.viewRangeRendered.to);
 };
 
-scout.Tree.prototype._updateDomNodeWidth = function($nodes) {
+scout.Tree.prototype._updateDomNodeWidth = function() {
   if (!this.isHorizontalScrollingEnabled()) {
     return;
   }
-  if (this.rendered && this.nodeWidthDirty) {
-    var nodes = this._visibleNodesInViewRange(),
-      maxNodeWidth = this.maxNodeWidth;
-    // find max-width
-    maxNodeWidth = nodes.reduce(function(aggr, node) {
-      return Math.max(node.width, aggr);
-    }, scout.nvl(maxNodeWidth, 0));
-    // set max width on all nodes
-    nodes.forEach(function(node) {
-      node.$node.cssWidth(maxNodeWidth);
-    });
-    this.nodeWidthDirty = false;
+  if (!this.rendered || !this.nodeWidthDirty) {
+    return;
   }
+  var nodes = this._visibleNodesInViewRange();
+  var maxNodeWidth = this.maxNodeWidth;
+  // find max-width
+  maxNodeWidth = nodes.reduce(function(aggr, node) {
+    return Math.max(node.width, aggr);
+  }, scout.nvl(maxNodeWidth, 0));
+  // set max width on all nodes
+  nodes.forEach(function(node) {
+    node.$node.cssWidth(maxNodeWidth);
+  });
+  this.nodeWidthDirty = false;
 };
 
 scout.Tree.prototype._cleanupNodes = function($nodes) {
@@ -840,17 +841,18 @@
 };
 
 scout.Tree.prototype._updateNodeDimensions = function() {
-  var emptyNode = this._createTreeNode();
-  var $node = this._renderNode(emptyNode).appendTo(this.$data);
-  this.nodeHeight = $node.outerHeight(true);
-  if (this.isHorizontalScrollingEnabled()) {
-    var oldNodeWidth = this.nodeWidth;
-    this.nodeWidth = $node.outerWidth(true);
-    if (oldNodeWidth !== this.nodeWidth) {
-      this.viewRangeDirty = true;
-    }
-  }
-  emptyNode.reset();
+//  var emptyNode = this._createTreeNode();
+//  var $node = this._renderNode(emptyNode).appendTo(this.$data);
+//  this.nodeHeight = $node.outerHeight(true);
+//  if (this.isHorizontalScrollingEnabled()) {
+//    var oldNodeWidth = this.nodeWidth;
+//    this.nodeWidth = $node.outerWidth(true);
+//    if (oldNodeWidth !== this.nodeWidth) {
+//      this.viewRangeDirty = true;
+//    }
+//  }
+//  emptyNode.reset();
+  this.nodeHeight = 30;
 };
 
 /**
@@ -2809,32 +2811,48 @@
 /**
  * Just insert node in DOM. NO check if in viewRange
  */
-scout.Tree.prototype._insertNodeInDOM = function(node, indexHint) {
+scout.Tree.prototype._insertNodesInDOM = function(nodes, indexHint) {
   if (!this.rendered && !this.rendering) {
     return;
   }
-  var index = indexHint === undefined ? this.visibleNodesFlat.indexOf(node) : indexHint;
-  if (index === -1 || !(this.viewRangeRendered.from + this.viewRangeSize >= index && this.viewRangeRendered.from <= index && this.viewRangeRendered.size() > 0) || node.attached) {
-    //node is not visible
-    return;
-  }
-  if (!node.rendered) {
-    this._renderNode(node);
-  }
-  node._decorate();
+  nodes.forEach(function(node) {
+    var index = indexHint === undefined ? this.visibleNodesFlat.indexOf(node) : indexHint;
+    if (index === -1 || !(this.viewRangeRendered.from + this.viewRangeSize >= index && this.viewRangeRendered.from <= index && this.viewRangeRendered.size() > 0) || node.attached) {
+      //node is not visible
+      return;
+    }
+    if (!node.rendered) {
+      this._renderNode(node);
+    }
+    node._decorate();
+    this._insertNodeInDOMAtPlace(node, index);
+    if (this.prevSelectedNode === node) {
+      this._highlightPrevSelectedNode();
+    }
+    node.rendered = true;
+    node.attached = true;
+  }, this);
+  this._installNodes(nodes);
+};
 
-  this._insertNodeInDOMAtPlace(node, index);
-  if (this.prevSelectedNode === node) {
-    this._highlightPrevSelectedNode();
-  }
-
-  node.height = node.$node.outerHeight(true);
+scout.Tree.prototype._installNodes = function(nodes) {
+  // The measuring is separated into 3 blocks for performance reasons -> separates reading and setting of styles
+  // 1. Prepare style for measuring
   if (this.isHorizontalScrollingEnabled()) {
-    var widthBackup = node.width ? node.width : 0,
-      displayBackup = node.$node.css('display');
-    node.$node.css('width', 'auto');
-    node.$node.css('display', 'inline-block');
-    var newWidth = node.$node.outerWidth();
+    nodes.forEach(function(node) {
+      node.$node.css('width', 'auto');
+      node.$node.css('display', 'inline-block');
+    }, this);
+  }
+
+  // 2. Measure
+  nodes.forEach(function(node) {
+    node.height = node.$node.outerHeight(true);
+    if (!this.isHorizontalScrollingEnabled()) {
+      return;
+    }
+    var newWidth = node.$node.css('width');
+    var widthBackup = node.width ? node.width : 0;
     if (widthBackup === this.maxNodeWidth && newWidth < this.maxNodeWidth) {
       this.maxNodeWidth = 0;
       this.nodeWidthDirty = true;
@@ -2842,14 +2860,20 @@
       this.maxNodeWidth = newWidth;
       this.nodeWidthDirty = true;
     }
-    if (!this.nodeWidthDirty) {
-      node.$node.css('width', this.maxNodeWidth);
-    }
-    node.$node.css('display', displayBackup);
     node.width = newWidth;
+  }, this);
+
+  // 3. Reset style
+  if (this.isHorizontalScrollingEnabled()) {
+    nodes.forEach(function(node) {
+      if (!this.nodeWidthDirty) {
+        node.$node.css('width', this.maxNodeWidth);
+      }
+      node.$node.css('display', '');
+    }, this);
   }
-  node.rendered = true;
-  node.attached = true;
+
+  this._updateDomNodeWidth(nodes);
 };
 
 /**
@@ -2902,7 +2926,7 @@
     return;
   }
   this._ensureNodeInDOM(node.parentNode, useAnimation, indexHint - 1);
-  this._insertNodeInDOM(node, indexHint);
+  this._insertNodesInDOM([node], indexHint);
   if (!node.rendered) {
     return;
   }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/jquery-3.3.1.js b/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/jquery-3.3.1.js
index 9b5206b..6c668e6 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/jquery-3.3.1.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/jquery-3.3.1.js
@@ -6579,7 +6579,10 @@
 		set: function( elem, value, extra ) {
 			var matches,
 				styles = getStyles( elem ),
-				isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+				// <BSI Patch> 20.12.2018 awe: added 'extra && ' to prevent the browser from 
+				// re-calculating layout/CSS-styles which bogs down Scouts layouting performance.
+				isBorderBox = extra && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+				// </BSI Patch>
 				subtract = extra && boxModelAdjustment(
 					elem,
 					dimension,
diff --git a/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/jquery-3.3.1_patch.js b/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/jquery-3.3.1_patch.js
index a99d744..bfd3701 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/jquery-3.3.1_patch.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/jquery-3.3.1_patch.js
@@ -12,7 +12,7 @@
 // As Scout no longer supports IE9 anyway and rarely makes use of overflow:scroll, disable fix 3699 completely for the moment.
 // As soon as jQuery is updated again, this patch may be removed after good testing.
 
-//The issue can be observed in the Scout UI e.g. in the Desktop header form-menus when starting Chrome with 90% zoom.
+// The issue can be observed in the Scout UI e.g. in the Desktop header form-menus when starting Chrome with 90% zoom.
 // It is important to refresh the page after the zoom has been set to 90% because jQuery only calculates the css-fixes once and caches the results!
 $.support.scrollboxSize = function() {
   return true;