diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index d665f756c1..258b82dea9 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -219,8 +219,6 @@ messaging: "チャット"
 upload: "アップロード"
 fromDrive: "ドライブから"
 fromUrl: "URLから"
-editWidgets: "ウィジェットを編集"
-exitEdit: "編集を終了"
 explore: "みつける"
 games: "Misskey Games"
 messageRead: "既読"
diff --git a/src/client/app.vue b/src/client/app.vue
index 22a56eb1f9..31c7543f36 100644
--- a/src/client/app.vue
+++ b/src/client/app.vue
@@ -18,8 +18,12 @@
 			</transition>
 		</div>
 		<div class="sub">
-			<fa :icon="faSearch"/>
-			<input type="search" class="search" :placeholder="$t('search')" v-model="searchQuery" v-autocomplete="{ model: 'searchQuery' }" :disabled="searchWait" @keypress="searchKeypress"/>
+			<button v-if="widgetsEditMode" class="_button edit active" @click="widgetsEditMode = false"><fa :icon="faGripVertical"/></button>
+			<button v-else class="_button edit" @click="widgetsEditMode = true"><fa :icon="faGripVertical"/></button>
+			<div class="search">
+				<fa :icon="faSearch"/>
+				<input type="search" :placeholder="$t('search')" v-model="searchQuery" v-autocomplete="{ model: 'searchQuery' }" :disabled="searchWait" @keypress="searchKeypress"/>
+			</div>
 			<button v-if="$store.getters.isSignedIn" class="post _buttonPrimary" @click="post()"><fa :icon="faPencilAlt"/></button>
 		</div>
 	</header>
@@ -86,7 +90,7 @@
 		</nav>
 	</transition>
 
-	<div class="contents">
+	<div class="contents" ref="contents">
 		<main ref="main">
 			<div class="content">
 				<transition :name="$store.state.device.animation ? 'page' : ''" mode="out-in" @enter="onTransition">
@@ -126,8 +130,6 @@
 					<template v-else>
 						<component class="widget" v-for="widget in widgets" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget"/>
 					</template>
-					<button ref="widgetsEditButton" v-if="widgetsEditMode" class="_button edit" @click="widgetsEditMode = false">{{ $t('exitEdit') }}</button>
-					<button ref="widgetsEditButton" v-else class="_button edit" @click="widgetsEditMode = true">{{ $t('editWidgets') }}</button>
 				</template>
 			</div>
 		</div>
@@ -150,8 +152,9 @@
 
 <script lang="ts">
 import Vue from 'vue';
-import { faChevronLeft, faHashtag, faBroadcastTower, faFireAlt, faEllipsisH, faPencilAlt, faBars, faTimes, faSearch, faUserCog, faCog, faUser, faHome, faStar, faCircle, faAt, faListUl, faPlus, faUserClock, faUsers, faTachometerAlt, faExchangeAlt, faGlobe, faChartBar, faCloud, faGamepad, faServer, faFileAlt, faSatellite, faInfoCircle, faQuestionCircle } from '@fortawesome/free-solid-svg-icons';
+import { faGripVertical, faChevronLeft, faHashtag, faBroadcastTower, faFireAlt, faEllipsisH, faPencilAlt, faBars, faTimes, faSearch, faUserCog, faCog, faUser, faHome, faStar, faCircle, faAt, faListUl, faPlus, faUserClock, faUsers, faTachometerAlt, faExchangeAlt, faGlobe, faChartBar, faCloud, faGamepad, faServer, faFileAlt, faSatellite, faInfoCircle, faQuestionCircle } from '@fortawesome/free-solid-svg-icons';
 import { faBell, faEnvelope, faLaugh, faComments } from '@fortawesome/free-regular-svg-icons';
+import { ResizeObserver } from '@juggle/resize-observer';
 import { v4 as uuid } from 'uuid';
 import i18n from './i18n';
 import { host } from './config';
@@ -184,7 +187,7 @@ export default Vue.extend({
 			enableWidgets: window.innerWidth >= 1100,
 			canBack: false,
 			disconnectedDialog: null as Promise<void> | null,
-			faChevronLeft, faComments, faHashtag, faBroadcastTower, faFireAlt, faEllipsisH, faPencilAlt, faBars, faTimes, faBell, faSearch, faUserCog, faCog, faUser, faHome, faStar, faCircle, faAt, faEnvelope, faListUl, faPlus, faUserClock, faLaugh, faUsers, faTachometerAlt, faExchangeAlt, faGlobe, faChartBar, faCloud, faServer
+			faGripVertical, faChevronLeft, faComments, faHashtag, faBroadcastTower, faFireAlt, faEllipsisH, faPencilAlt, faBars, faTimes, faBell, faSearch, faUserCog, faCog, faUser, faHome, faStar, faCircle, faAt, faEnvelope, faListUl, faPlus, faUserClock, faLaugh, faUsers, faTachometerAlt, faExchangeAlt, faGlobe, faChartBar, faCloud, faServer
 		};
 	},
 
@@ -256,25 +259,33 @@ export default Vue.extend({
 				});
 			}
 		});
-
-		// https://stackoverflow.com/questions/33891709/when-flexbox-items-wrap-in-column-mode-container-does-not-grow-its-width
-		if (this.enableWidgets) {
-			setInterval(() => {
-				if (!this.$refs.widgetsEditButton) return;
-
-				const width = this.$refs.widgetsEditButton.offsetLeft + 300;
-				this.$refs.widgets.style.width = width + 'px';
-			}, 1000);
-		}
 	},
 
 	mounted() {
+		// https://stackoverflow.com/questions/33891709/when-flexbox-items-wrap-in-column-mode-container-does-not-grow-its-width
+		if (this.enableWidgets) {
+			const adjustWidgetsWidth = () => {
+				const lastChild = this.$refs.widgets.children[this.$refs.widgets.children.length - 1];
+				if (lastChild == null) return;
+
+				const width = lastChild.offsetLeft + 300;
+				this.$refs.widgets.style.width = width + 'px';
+			};
+			setInterval(adjustWidgetsWidth, 1000);
+		}
+
 		const adjustTitlePosition = () => {
 			this.$refs.title.style.left = (this.$refs.main.getBoundingClientRect().left - this.$refs.nav.offsetWidth) + 'px';
 		};
 
 		adjustTitlePosition();
 
+		const ro = new ResizeObserver((entries, observer) => {
+			adjustTitlePosition();
+		});
+		
+		ro.observe(this.$refs.contents);
+
 		window.addEventListener('resize', adjustTitlePosition);
 	},
 
@@ -714,30 +725,42 @@ export default Vue.extend({
 				display: none;
 			}
 
-			> [data-icon] {
-				position: absolute;
-				top: 0;
-				left: 16px;
-				height: $header-height;
-				pointer-events: none;
-				font-size: 16px;
+			> .edit {
+				padding: 16px;
+
+				&.active {
+					color: var(--accent);
+				}
 			}
 
 			> .search {
-				$margin: 8px;
-				width: calc(100% - #{$post-button-size + $post-button-margin + $margin});
-				box-sizing: border-box;
-				margin-right: $margin;
-				padding: 0 12px 0 42px;
-				font-size: 1rem;
-				line-height: 38px;
-				border: none;
-				border-radius: 38px;
-				color: var(--fg);
-				background: var(--bg);
+				position: relative;
 
-				&:focus {
-					outline: none;
+				> input {
+					$margin: 8px;
+					width: 200px;
+					box-sizing: border-box;
+					margin-right: $margin;
+					padding: 0 12px 0 42px;
+					font-size: 1rem;
+					line-height: 38px;
+					border: none;
+					border-radius: 38px;
+					color: var(--fg);
+					background: var(--bg);
+
+					&:focus {
+						outline: none;
+					}
+				}
+
+				> [data-icon] {
+					position: absolute;
+					top: 0;
+					left: 16px;
+					height: 100%;
+					pointer-events: none;
+					font-size: 16px;
 				}
 			}
 
@@ -976,12 +999,6 @@ export default Vue.extend({
 					margin: 0 auto;
 				}
 
-				> .edit {
-					display: block;
-					font-size: 0.9em;
-					margin: 0 auto;
-				}
-
 				.customize-container {
 					margin: 8px 0;
 					background: #fff;