diff --git a/bigbluebutton-html5/imports/ui/components/media/styles.scss b/bigbluebutton-html5/imports/ui/components/media/styles.scss
index 106191a85a27f80a812fd1e4c69dc89209cb7979..fc83c5f839842f74761f89e701b89020e06989db 100644
--- a/bigbluebutton-html5/imports/ui/components/media/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/media/styles.scss
@@ -106,7 +106,6 @@
   position: absolute;
   width: 100%;
   z-index: 9999;
-  cursor: grabbing;
 }
 
 .dropZoneTop {
diff --git a/bigbluebutton-html5/imports/ui/components/media/webcam-draggable-overlay/component.jsx b/bigbluebutton-html5/imports/ui/components/media/webcam-draggable-overlay/component.jsx
index 42f14f9d926291f3325025ad9841f3133552016e..3513d555247618019a9c32e9a17fbc98d2ae17e0 100644
--- a/bigbluebutton-html5/imports/ui/components/media/webcam-draggable-overlay/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/media/webcam-draggable-overlay/component.jsx
@@ -100,9 +100,11 @@ export default class WebcamDraggableOverlay extends Component {
       isVideoLoaded: false,
       isMinWidth: false,
       userLength: 0,
+      shouldUpdatePosition: true,
     };
 
     this.updateWebcamPositionByResize = this.updateWebcamPositionByResize.bind(this);
+    this.eventVideoFocusChangeListener = this.eventVideoFocusChangeListener.bind(this);
 
     this.eventResizeListener = _.throttle(
       this.updateWebcamPositionByResize,
@@ -125,8 +127,10 @@ export default class WebcamDraggableOverlay extends Component {
     this.setResetPosition = this.setResetPosition.bind(this);
     this.setInitialReferencePoint = this.setInitialReferencePoint.bind(this);
     this.setLastPosition = this.setLastPosition.bind(this);
+    this.setShouldUpdatePosition = this.setShouldUpdatePosition.bind(this);
     this.setLastWebcamPosition = this.setLastWebcamPosition.bind(this);
     this.setisMinWidth = this.setisMinWidth.bind(this);
+    this.setDropOnBottom = this.setDropOnBottom.bind(this);
 
     this.dropZoneTopEnterHandler = this.dropZoneTopEnterHandler.bind(this);
     this.dropZoneTopLeaveHandler = this.dropZoneTopLeaveHandler.bind(this);
@@ -146,6 +150,7 @@ export default class WebcamDraggableOverlay extends Component {
       && !resetPosition) this.setResetPosition(true);
 
     window.addEventListener('resize', this.eventResizeListener);
+    window.addEventListener('videoFocusChange', this.eventVideoFocusChangeListener);
 
     fullscreenChangedEvents.forEach((event) => {
       document.addEventListener(event, this.handleFullscreenChange);
@@ -158,9 +163,18 @@ export default class WebcamDraggableOverlay extends Component {
   }
 
   componentDidUpdate(prevProps, prevState) {
-    const { userLength } = this.state;
-    if (userLength !== prevState.userLength) {
-      this.setLastWebcamPosition({ x: 0 });
+    const { swapLayout } = this.props;
+    const { userLength, lastPosition } = this.state;
+    const { y } = lastPosition;
+    // if (prevProps.swapLayout && !swapLayout && userLength === 1) {
+    //   this.setShouldUpdatePosition(false);
+    // }
+    if (prevProps.swapLayout && !swapLayout && userLength > 1) {
+      this.setLastPosition(0, y);
+    }
+    if (prevState.userLength === 1 && userLength > 1) {
+      this.setDropOnBottom(true);
+      this.setResetPosition(true);
     }
   }
 
@@ -170,6 +184,8 @@ export default class WebcamDraggableOverlay extends Component {
     });
 
     document.removeEventListener('webcamFullscreenButtonChange', this.fullscreenButtonChange);
+    document.removeEventListener('videoListUsersChange', this.getVideoListUsersChange);
+    document.removeEventListener('videoFocusChange', this.eventVideoFocusChangeListener);
   }
 
   getVideoListUsersChange() {
@@ -189,14 +205,22 @@ export default class WebcamDraggableOverlay extends Component {
     this.setState({ lastPosition: { x, y } });
   }
 
+  setShouldUpdatePosition(shouldUpdatePosition) {
+    this.setState({ shouldUpdatePosition });
+  }
+
+  setDropOnBottom(dropOnBottom) {
+    this.setState({ dropOnBottom });
+  }
+
   setInitialReferencePoint() {
     const { refMediaContainer } = this.props;
-    const { userLength } = this.state;
+    const { userLength, shouldUpdatePosition } = this.state;
     const { current: mediaContainer } = refMediaContainer;
 
     const webcamBySelector = WebcamDraggableOverlay.getWebcamBySelector();
 
-    if (webcamBySelector && mediaContainer) {
+    if (webcamBySelector && mediaContainer && shouldUpdatePosition) {
       if (userLength === 0) this.getVideoListUsersChange();
 
       let x = 0;
@@ -231,12 +255,12 @@ export default class WebcamDraggableOverlay extends Component {
   setLastWebcamPosition() {
     const { refMediaContainer } = this.props;
     const { current: mediaContainer } = refMediaContainer;
-    const { initialRectPosition, userLength } = this.state;
+    const { initialRectPosition, userLength, shouldUpdatePosition } = this.state;
 
     const { x: initX, y: initY } = initialRectPosition;
     const webcamBySelector = WebcamDraggableOverlay.getWebcamBySelector();
 
-    if (webcamBySelector && mediaContainer) {
+    if (webcamBySelector && mediaContainer && shouldUpdatePosition) {
       const webcamBySelectorRect = webcamBySelector.getBoundingClientRect();
       const {
         left: webcamLeft,
@@ -260,15 +284,17 @@ export default class WebcamDraggableOverlay extends Component {
       } else {
         x = 0 - initX;
       }
-      if (webcamXByMedia > initX) x = -(initY - 10);
       if (userLength > 1) x = 0;
 
-      y = webcamYByMedia - (initY - 10);
+      if (webcamYByMedia > 0) {
+        y = webcamYByMedia - initY;
+      } else {
+        y = 0 - initY;
+      }
 
       if (webcamYByMedia > initY) {
         y = -10;
       }
-      if (webcamYByMedia < 0) y = -(initY - 10);
 
       this.setLastPosition(x, y);
     }
@@ -293,13 +319,8 @@ export default class WebcamDraggableOverlay extends Component {
       isVideoLoaded,
       isMinWidth,
     } = this.state;
-    const webcamBySelectorCount = WebcamDraggableOverlay.getWebcamBySelectorCount();
 
     if (isVideoLoaded) {
-      if (WebcamDraggableOverlay.isOverlayAbsolute() && webcamBySelectorCount > 1) {
-        this.setInitialReferencePoint();
-        this.setLastWebcamPosition();
-      }
       this.setInitialReferencePoint();
       this.setLastWebcamPosition();
     }
@@ -313,6 +334,13 @@ export default class WebcamDraggableOverlay extends Component {
     }
   }
 
+  eventVideoFocusChangeListener() {
+    setTimeout(() => {
+      this.setInitialReferencePoint();
+      this.setLastWebcamPosition();
+    }, 500);
+  }
+
   handleFullscreenChange() {
     if (document.fullscreenElement
       || document.webkitFullscreenElement
@@ -425,7 +453,20 @@ export default class WebcamDraggableOverlay extends Component {
       hideOverlay,
       disableVideo,
       audioModalIsOpen,
+      refMediaContainer,
     } = this.props;
+    const { current: mediaContainer } = refMediaContainer;
+
+    let mediaContainerRect;
+    let mediaHeight;
+    if (mediaContainer) {
+      mediaContainerRect = mediaContainer.getBoundingClientRect();
+      const {
+        height,
+      } = mediaContainerRect;
+      mediaHeight = height;
+    }
+
 
     const {
       dragging,
@@ -486,7 +527,7 @@ export default class WebcamDraggableOverlay extends Component {
     });
 
     const cursor = () => {
-      if ((!swapLayout || !isFullScreen || !BROWSER_ISMOBILE) && !dragging && !isMinWidth) return 'grab';
+      if ((!swapLayout || !isFullScreen || !BROWSER_ISMOBILE || !isMinWidth) && !dragging) return 'grab';
       if (dragging) return 'grabbing';
       return 'default';
     };
@@ -523,6 +564,8 @@ export default class WebcamDraggableOverlay extends Component {
                 ? (
                   <VideoProviderContainer
                     cursor={cursor()}
+                    swapLayout={swapLayout}
+                    mediaHeight={mediaHeight}
                     onMount={this.videoMounted}
                     onUpdate={this.videoUpdated}
                   />
diff --git a/bigbluebutton-html5/imports/ui/components/video-provider/component.jsx b/bigbluebutton-html5/imports/ui/components/video-provider/component.jsx
index 2cf9f87fb1591c07086ba7d54326213baa2a820c..804ab478665b907a2924b628c46881d02a70c4cf 100755
--- a/bigbluebutton-html5/imports/ui/components/video-provider/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/video-provider/component.jsx
@@ -190,9 +190,13 @@ class VideoProvider extends Component {
             && peer.peerConnection.getRemoteStreams().length > 0;
 
           if (hasLocalStream) {
-            this.customGetStats(peer.peerConnection, peer.peerConnection.getLocalStreams()[0].getVideoTracks()[0], (stats => updateWebcamStats(id, stats)), true);
+            this.customGetStats(peer.peerConnection,
+              peer.peerConnection.getLocalStreams()[0].getVideoTracks()[0],
+              (stats => updateWebcamStats(id, stats)), true);
           } else if (hasRemoteStream) {
-            this.customGetStats(peer.peerConnection, peer.peerConnection.getRemoteStreams()[0].getVideoTracks()[0], (stats => updateWebcamStats(id, stats)), true);
+            this.customGetStats(peer.peerConnection,
+              peer.peerConnection.getRemoteStreams()[0].getVideoTracks()[0],
+              (stats => updateWebcamStats(id, stats)), true);
           }
         });
       }, 5000);
@@ -833,9 +837,9 @@ class VideoProvider extends Component {
 
       let videoBitrate;
       if (videoStats.packetsReceived > 0) { // Remote video
-        videoLostPercentage = ((videoStats
-          .packetsLost / ((videoStats
-            .packetsLost + videoStats.packetsReceived) * 100)) || 0).toFixed(1);
+        videoLostPercentage = ((videoStats.packetsLost / (
+          (videoStats.packetsLost + videoStats.packetsReceived) * 100
+        )) || 0).toFixed(1);
         videoBitrate = Math.floor(videoKbitsReceivedPerSecond || 0);
         videoLostRecentPercentage = ((videoIntervalPacketsLost / ((videoIntervalPacketsLost
           + videoIntervalPacketsReceived) * 100)) || 0).toFixed(1);
@@ -1005,10 +1009,18 @@ class VideoProvider extends Component {
     const { socketOpen } = this.state;
     if (!socketOpen) return null;
 
-    const { users, enableVideoStats, cursor } = this.props;
+    const {
+      users,
+      enableVideoStats,
+      cursor,
+      swapLayout,
+      mediaHeight,
+    } = this.props;
     return (
       <VideoList
         cursor={cursor}
+        swapLayout={swapLayout}
+        mediaHeight={mediaHeight}
         users={users}
         onMount={this.createVideoTag}
         getStats={this.getStats}
diff --git a/bigbluebutton-html5/imports/ui/components/video-provider/container.jsx b/bigbluebutton-html5/imports/ui/components/video-provider/container.jsx
index 9cee75901ca36197ce581157b4c309c3c1aa43d6..00b68f9b2e1f9719982c05fe367095c2dad732ab 100755
--- a/bigbluebutton-html5/imports/ui/components/video-provider/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/video-provider/container.jsx
@@ -11,6 +11,8 @@ const VideoProviderContainer = ({ children, ...props }) => {
 
 export default withTracker(props => ({
   cursor: props.cursor,
+  swapLayout: props.swapLayout,
+  mediaHeight: props.mediaHeight,
   meetingId: VideoService.meetingId(),
   users: VideoService.getAllUsersVideo(),
   userId: VideoService.userId(),
diff --git a/bigbluebutton-html5/imports/ui/components/video-provider/video-list/component.jsx b/bigbluebutton-html5/imports/ui/components/video-provider/video-list/component.jsx
index 7a18d9a44344f52e4a4f0f387cc64074180ac2e2..8ba43a8abf6f628b44ef4eef28a32bf7cea87f44 100644
--- a/bigbluebutton-html5/imports/ui/components/video-provider/video-list/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/video-provider/video-list/component.jsx
@@ -47,12 +47,20 @@ class VideoList extends Component {
     this.setState({
       focusedId: focusedId !== id ? id : false,
     }, this.handleCanvasResize);
-    window.dispatchEvent(new Event('resize'));
+    window.dispatchEvent(new Event('videoFocusChange'));
   }
 
   renderVideoList() {
     const {
-      intl, users, onMount, getStats, stopGettingStats, enableVideoStats, cursor,
+      intl,
+      users,
+      onMount,
+      getStats,
+      stopGettingStats,
+      enableVideoStats,
+      cursor,
+      swapLayout,
+      mediaHeight,
     } = this.props;
     const { focusedId } = this.state;
 
@@ -73,7 +81,8 @@ class VideoList extends Component {
         <div
           key={user.id}
           className={cx({
-            [styles.videoListItem]: true,
+            [styles.videoListItem]: !swapLayout,
+            [styles.videoListItemSwapLayout]: swapLayout,
             [styles.focused]: focusedId === user.id && users.length > 2,
           })}
           style={{
@@ -88,6 +97,8 @@ class VideoList extends Component {
             getStats={(videoRef, callback) => getStats(user.id, videoRef, callback)}
             stopGettingStats={() => stopGettingStats(user.id)}
             enableVideoStats={enableVideoStats}
+            swapLayout={swapLayout}
+            mediaHeight={mediaHeight}
           />
         </div>
       );
@@ -95,16 +106,27 @@ class VideoList extends Component {
   }
 
   render() {
-    const { users } = this.props;
+    const { users, swapLayout } = this.props;
+
+    const canvasClassName = cx({
+      [styles.videoCanvas]: !swapLayout,
+      [styles.videoCanvasSwapLayout]: swapLayout,
+    });
+
+    const videoListClassName = cx({
+      [styles.videoList]: !swapLayout,
+      [styles.videoListSwapLayout]: swapLayout,
+    });
+
     return (
       <div
         ref={(ref) => { this.canvas = ref; }}
-        className={styles.videoCanvas}
+        className={canvasClassName}
       >
         {!users.length ? null : (
           <div
             ref={(ref) => { this.grid = ref; }}
-            className={styles.videoList}
+            className={videoListClassName}
           >
             {this.renderVideoList()}
           </div>
diff --git a/bigbluebutton-html5/imports/ui/components/video-provider/video-list/styles.scss b/bigbluebutton-html5/imports/ui/components/video-provider/video-list/styles.scss
index 56d924289be289e16d098d63e53aeb2d2be63fa6..154a71077df25be7a8dd7d481a029d4c7b841ae2 100755
--- a/bigbluebutton-html5/imports/ui/components/video-provider/video-list/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/video-provider/video-list/styles.scss
@@ -11,18 +11,33 @@
   --audio-indicator-fs: 75%;
   position: relative;
   width: 100%;
+  min-height: calc(var(--video-width) / var(--video-ratio));
+  height: 100%;
   top: 0;
   left: 0;
   right: 0;
   bottom: 0;
   align-items: center;
   justify-content: center;
+}
+
+.videoCanvasSwapLayout {
+  --cam-dropdown-width: 70%;
+  --audio-indicator-width: 1.12rem;
+  --audio-indicator-fs: 75%;
+  position: relative;
+  width: 100%;
   min-height: calc(var(--video-width) / var(--video-ratio));
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  align-items: center;
+  justify-content: center;
 }
 
 .videoList {
   display: grid;
-  padding: 10px;
   border-radius: 5px;
 
   min-height: calc(var(--video-width) / var(--video-ratio));
@@ -41,6 +56,24 @@
   }
 }
 
+.videoListSwapLayout {
+  display: grid;
+  padding: 10px;
+  border-radius: 5px;
+  min-height: calc(var(--video-width) / var(--video-ratio));
+  grid-template-columns: repeat(auto-fit, minmax(var(--video-width), 1fr));
+  grid-auto-columns: minmax(var(--video-width), 1fr);
+  grid-auto-rows: 1fr;
+  grid-gap: 5px;
+  align-items: center;
+  justify-content: center;
+  grid-auto-flow: row;
+
+  @include mq($medium-up) {
+    grid-gap: 10px;
+  }
+}
+
 .videoListItem {
   display: flex;
   max-width: fit-content;
@@ -62,6 +95,25 @@
   min-height: calc(var(--video-width) / var(--video-ratio));
 }
 
+.videoListItemSwapLayout {
+  display: flex;
+  max-width: -moz-fit-content;
+  max-height: -moz-fit-content;
+  width: 100%;
+  height: 100%;
+
+  &.focused {
+    grid-column: 1 / span 2;
+    grid-row: 1 / span 2;
+    width: 100%;
+    min-width: 100%;
+    max-width: 100%;
+    height: 100%;
+    min-height: 100%;
+    max-height: 100%;
+  }
+}
+
 .content {
   position: relative;
   min-width: 100%;
@@ -107,6 +159,48 @@
   }
 }
 
+.contentSwapLayout {
+  position: relative;
+  min-width: 100%;
+  height: 100%;
+  min-height: 100%;
+  border-radius: 5px;
+
+  background-color: var(--color-gray);
+
+  width: 100%;
+
+  &::after {
+    content: "";
+    position: absolute;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    left: 0;
+    border: 5px solid var(--color-white-with-transparency);
+    border-radius: 5px;
+    opacity: 0;
+    pointer-events: none;
+
+    :global(.animationsEnabled) & {
+      transition: opacity .1s;
+    }
+  }
+
+  &.talking::after {
+    opacity: 1;
+  }
+
+  .focused & {
+    width: 100%;
+    min-width: 100%;
+    max-width: 100%;
+    height: 100%;
+    min-height: 100%;
+    max-height: 100%;
+  }
+}
+
 .contentLoading {
   width: var(--video-width);
   min-width: var(--video-width);
@@ -114,8 +208,12 @@
   min-height: calc(var(--video-width) / var(--video-ratio));
 }
 
-%media-area {
+.contentLoadingSwapLayout {
+  width: 100%;
+  height: 100%;
+}
 
+%media-area {
   position: relative;
   height: 100%;
   width: 100%;
diff --git a/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/component.jsx b/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/component.jsx
index 46a1d2b782561425485f8a2cb8a613e211bddb48..29a4e49af6ab9ed55a9c14878478d7aad1b5a669 100755
--- a/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/component.jsx
@@ -129,7 +129,9 @@ class VideoListItem extends Component {
 
   render() {
     const { showStats, stats, videoIsReady } = this.state;
-    const { user, numOfUsers } = this.props;
+    const {
+      user, numOfUsers, swapLayout, mediaHeight,
+    } = this.props;
     const availableActions = this.getAvailableActions();
     const enableVideoMenu = Meteor.settings.public.kurento.enableVideoMenu || false;
 
@@ -138,13 +140,18 @@ class VideoListItem extends Component {
 
     return (
       <div className={cx({
-        [styles.content]: true,
+        [styles.content]: !swapLayout,
+        [styles.contentSwapLayout]: swapLayout,
         [styles.talking]: user.isTalking,
-        [styles.contentLoading]: !videoIsReady,
+        [styles.contentLoading]: !videoIsReady && !swapLayout,
+        [styles.contentLoadingSwapLayout]: !videoIsReady && swapLayout,
       })}
       >
         {!videoIsReady && <div className={styles.connecting} />}
         <video
+          style={{
+            maxHeight: mediaHeight - 20, // 20 is margin
+          }}
           muted
           className={cx({
             [styles.media]: true,