diff --git a/dc.js b/dc.js
index b06fd0896..75d9f2c52 100644
--- a/dc.js
+++ b/dc.js
@@ -4195,9 +4195,11 @@ dc.barChart = function (parent, chartGroup) {
     var _gap = DEFAULT_GAP_BETWEEN_BARS;
     var _centerBar = false;
     var _alwaysUseRounding = false;
-
+    
     var _barWidth;
 
+    var _renderType = 'stack';
+
     dc.override(_chart, 'rescale', function () {
         _chart._rescale();
         _barWidth = undefined;
@@ -4232,10 +4234,15 @@ dc.barChart = function (parent, chartGroup) {
         });
     };
 
-    function barHeight(d) {
+    function stackBarHeight(d) {
         return dc.utils.safeNumber(Math.abs(_chart.y()(d.y + d.y0) - _chart.y()(d.y0)));
     }
 
+    function groupBarHeight(d){
+        var margin = _chart.margins();
+        return dc.utils.safeNumber(Math.abs(_chart.height() - margin.top - margin.bottom - _chart.y()(d.y))); 
+    }
+
     function renderBars(layer, layerIndex, d) {
         var bars = layer.selectAll('rect.bar')
             .data(d.values, dc.pluck('x'));
@@ -4254,34 +4261,88 @@ dc.barChart = function (parent, chartGroup) {
         if (_chart.isOrdinal()) {
             bars.on('click', _chart.onClick);
         }
-
-        dc.transition(bars, _chart.transitionDuration())
-            .attr('x', function (d) {
-                var x = _chart.x()(d.x);
-                if (_centerBar) {
-                    x -= _barWidth / 2;
-                }
-                if (_chart.isOrdinal() && _gap !== undefined) {
-                    x += _gap / 2;
-                }
-                return dc.utils.safeNumber(x);
+        
+        if(_renderType === 'stack'){
+          dc.transition(bars, _chart.transitionDuration())
+              .attr('x', function (d) {
+                  var x = _chart.x()(d.x);
+                  if (_centerBar) {
+                      x -= _barWidth / 2;
+                  }
+                  if (_chart.isOrdinal() && _gap !== undefined) {
+                      x += _gap / 2;
+                  }
+                  return dc.utils.safeNumber(x);
+              })
+              .attr('y', function (d) {
+                  var y = _chart.y()(d.y + d.y0);
+
+                  if (d.y < 0) {
+                      y -= stackBarHeight(d);
+                  }
+
+                  return dc.utils.safeNumber(y);
+              })
+              .attr('width', _barWidth)
+              .attr('height', function (d) {
+                  return stackBarHeight(d);
+              })
+              .attr('fill', dc.pluck('data', _chart.getColor))
+              .select('title').text(dc.pluck('data', _chart.title(d.name)));
+
+        }
+        else if(_renderType === 'group'){
+          var groups = _chart.stack().map(function(d){ return d.name;});
+          var groupRange = d3.scale.ordinal().domain(groups).rangePoints([0, _barWidth - _barWidth/2]);
+          dc.transition(bars, _chart.transitionDuration())
+            .attr('x', function(d, i){
+                  var x = _chart.x()(d.x) + groupRange(d.layer);
+                  if (_centerBar) {
+                      x -= _barWidth / 2;
+                  }
+                  if (_chart.isOrdinal() && _gap !== undefined) {
+                      x += _gap / 2;
+                  }
+                  return dc.utils.safeNumber(x);
             })
-            .attr('y', function (d) {
-                var y = _chart.y()(d.y + d.y0);
-
-                if (d.y < 0) {
-                    y -= barHeight(d);
-                }
-
+            .attr('width', (_barWidth/_chart.stack().length) - 3)
+            .attr('y', function(d) {
+                var y = _chart.y()(d.y);
+                
+                  if (d.y < 0) {
+                      y -= groupBarHeight(d);
+                  }
                 return dc.utils.safeNumber(y);
             })
-            .attr('width', _barWidth)
-            .attr('height', function (d) {
-                return barHeight(d);
+            .attr('height', function(d){
+              return groupBarHeight(d);
+            });
+        }
+        else if(_renderType === 'overlap'){
+          dc.transition(bars, _chart.transitionDuration())
+            .attr('x', function(d, i){
+                  var x = _chart.x()(d.x);
+                  if (_centerBar) {
+                      x -= _barWidth / 2;
+                  }
+                  if (_chart.isOrdinal() && _gap !== undefined) {
+                      x += _gap / 2;
+                  }
+                  return dc.utils.safeNumber(x);
             })
-            .attr('fill', dc.pluck('data', _chart.getColor))
-            .select('title').text(dc.pluck('data', _chart.title(d.name)));
-
+            .attr('y', function(d) {
+                var y = _chart.y()(d.y);
+                
+                  if (d.y < 0) {
+                      y -= groupBarHeight(d);
+                  }
+                return dc.utils.safeNumber(y);
+            })
+            .attr('width', _barWidth)
+            .attr('height', function(d){
+              return groupBarHeight(d);
+            });
+        }
         dc.transition(bars.exit(), _chart.transitionDuration())
             .attr('height', 0)
             .remove();
@@ -4453,6 +4514,14 @@ dc.barChart = function (parent, chartGroup) {
             .classed('fadeout', false);
     };
 
+    _chart.renderType = function(_rendtype){
+      if(!arguments.length){
+        return _renderType;
+      }
+      _renderType = _rendtype;
+      return _chart;
+    };
+
     dc.override(_chart, 'xAxisMax', function () {
         var max = this._xAxisMax();
         if ('resolution' in _chart.xUnits()) {
@@ -4462,6 +4531,24 @@ dc.barChart = function (parent, chartGroup) {
         return max;
     });
 
+    dc.override(_chart, 'yAxisMax', function(){
+      var max;
+      if(_renderType === 'stack'){
+        max = d3.max(flattenStack(), function(p){
+          return p.y + p.y0;
+        });
+      }
+      else if(_renderType === 'group' || _renderType === 'overlap'){
+        max = d3.max(flattenStack(), dc.pluck('y'));
+      }
+      return dc.utils.add(max, _chart.yAxisPadding());
+    });
+  
+    // Not dry but need flattenStack here and don't want to expose it, possible move to util
+    function flattenStack() {
+        var valueses = _chart.data().map(function (layer) { return layer.values; });
+        return Array.prototype.concat.apply([], valueses);
+    }
     return _chart.anchor(parent, chartGroup);
 };
 
diff --git a/src/bar-chart.js b/src/bar-chart.js
index 4655a83d2..e1a9df004 100644
--- a/src/bar-chart.js
+++ b/src/bar-chart.js
@@ -42,9 +42,11 @@ dc.barChart = function (parent, chartGroup) {
     var _gap = DEFAULT_GAP_BETWEEN_BARS;
     var _centerBar = false;
     var _alwaysUseRounding = false;
-
+    
     var _barWidth;
 
+    var _renderType = 'stack';
+
     dc.override(_chart, 'rescale', function () {
         _chart._rescale();
         _barWidth = undefined;
@@ -79,10 +81,15 @@ dc.barChart = function (parent, chartGroup) {
         });
     };
 
-    function barHeight(d) {
+    function stackBarHeight(d) {
         return dc.utils.safeNumber(Math.abs(_chart.y()(d.y + d.y0) - _chart.y()(d.y0)));
     }
 
+    function groupBarHeight(d){
+        var margin = _chart.margins();
+        return dc.utils.safeNumber(Math.abs(_chart.height() - margin.top - margin.bottom - _chart.y()(d.y))); 
+    }
+
     function renderBars(layer, layerIndex, d) {
         var bars = layer.selectAll('rect.bar')
             .data(d.values, dc.pluck('x'));
@@ -101,34 +108,88 @@ dc.barChart = function (parent, chartGroup) {
         if (_chart.isOrdinal()) {
             bars.on('click', _chart.onClick);
         }
+        
+        if(_renderType === 'stack'){
+          dc.transition(bars, _chart.transitionDuration())
+              .attr('x', function (d) {
+                  var x = _chart.x()(d.x);
+                  if (_centerBar) {
+                      x -= _barWidth / 2;
+                  }
+                  if (_chart.isOrdinal() && _gap !== undefined) {
+                      x += _gap / 2;
+                  }
+                  return dc.utils.safeNumber(x);
+              })
+              .attr('y', function (d) {
+                  var y = _chart.y()(d.y + d.y0);
+
+                  if (d.y < 0) {
+                      y -= stackBarHeight(d);
+                  }
+
+                  return dc.utils.safeNumber(y);
+              })
+              .attr('width', _barWidth)
+              .attr('height', function (d) {
+                  return stackBarHeight(d);
+              })
+              .attr('fill', dc.pluck('data', _chart.getColor))
+              .select('title').text(dc.pluck('data', _chart.title(d.name)));
 
-        dc.transition(bars, _chart.transitionDuration())
-            .attr('x', function (d) {
-                var x = _chart.x()(d.x);
-                if (_centerBar) {
-                    x -= _barWidth / 2;
-                }
-                if (_chart.isOrdinal() && _gap !== undefined) {
-                    x += _gap / 2;
-                }
-                return dc.utils.safeNumber(x);
+        }
+        else if(_renderType === 'group'){
+          var groups = _chart.stack().map(function(d){ return d.name;});
+          var groupRange = d3.scale.ordinal().domain(groups).rangePoints([0, _barWidth - _barWidth/2]);
+          dc.transition(bars, _chart.transitionDuration())
+            .attr('x', function(d, i){
+                  var x = _chart.x()(d.x) + groupRange(d.layer);
+                  if (_centerBar) {
+                      x -= _barWidth / 2;
+                  }
+                  if (_chart.isOrdinal() && _gap !== undefined) {
+                      x += _gap / 2;
+                  }
+                  return dc.utils.safeNumber(x);
             })
-            .attr('y', function (d) {
-                var y = _chart.y()(d.y + d.y0);
-
-                if (d.y < 0) {
-                    y -= barHeight(d);
-                }
-
+            .attr('width', (_barWidth/_chart.stack().length) - 3)
+            .attr('y', function(d) {
+                var y = _chart.y()(d.y);
+                
+                  if (d.y < 0) {
+                      y -= groupBarHeight(d);
+                  }
                 return dc.utils.safeNumber(y);
             })
-            .attr('width', _barWidth)
-            .attr('height', function (d) {
-                return barHeight(d);
+            .attr('height', function(d){
+              return groupBarHeight(d);
+            });
+        }
+        else if(_renderType === 'overlap'){
+          dc.transition(bars, _chart.transitionDuration())
+            .attr('x', function(d, i){
+                  var x = _chart.x()(d.x);
+                  if (_centerBar) {
+                      x -= _barWidth / 2;
+                  }
+                  if (_chart.isOrdinal() && _gap !== undefined) {
+                      x += _gap / 2;
+                  }
+                  return dc.utils.safeNumber(x);
             })
-            .attr('fill', dc.pluck('data', _chart.getColor))
-            .select('title').text(dc.pluck('data', _chart.title(d.name)));
-
+            .attr('y', function(d) {
+                var y = _chart.y()(d.y);
+                
+                  if (d.y < 0) {
+                      y -= groupBarHeight(d);
+                  }
+                return dc.utils.safeNumber(y);
+            })
+            .attr('width', _barWidth)
+            .attr('height', function(d){
+              return groupBarHeight(d);
+            });
+        }
         dc.transition(bars.exit(), _chart.transitionDuration())
             .attr('height', 0)
             .remove();
@@ -300,6 +361,14 @@ dc.barChart = function (parent, chartGroup) {
             .classed('fadeout', false);
     };
 
+    _chart.renderType = function(_rendtype){
+      if(!arguments.length){
+        return _renderType;
+      }
+      _renderType = _rendtype;
+      return _chart;
+    };
+
     dc.override(_chart, 'xAxisMax', function () {
         var max = this._xAxisMax();
         if ('resolution' in _chart.xUnits()) {
@@ -309,5 +378,23 @@ dc.barChart = function (parent, chartGroup) {
         return max;
     });
 
+    dc.override(_chart, 'yAxisMax', function(){
+      var max;
+      if(_renderType === 'stack'){
+        max = d3.max(flattenStack(), function(p){
+          return p.y + p.y0;
+        });
+      }
+      else if(_renderType === 'group' || _renderType === 'overlap'){
+        max = d3.max(flattenStack(), dc.pluck('y'));
+      }
+      return dc.utils.add(max, _chart.yAxisPadding());
+    });
+  
+    // Not dry but need flattenStack here and don't want to expose it, possible move to util
+    function flattenStack() {
+        var valueses = _chart.data().map(function (layer) { return layer.values; });
+        return Array.prototype.concat.apply([], valueses);
+    }
     return _chart.anchor(parent, chartGroup);
 };