diff --git a/src/client/app.vue b/src/client/app.vue
index d2707cdf01..fdd050c714 100644
--- a/src/client/app.vue
+++ b/src/client/app.vue
@@ -91,7 +91,7 @@
 		</nav>
 	</transition>
 
-	<div class="contents" ref="contents">
+	<div class="contents" ref="contents" :class="{ wallpaper }">
 		<main ref="main">
 			<div class="content">
 				<transition :name="$store.state.device.animation ? 'page' : ''" mode="out-in" @enter="onTransition">
@@ -189,6 +189,7 @@ export default Vue.extend({
 			isDesktop: window.innerWidth >= 1100,
 			canBack: false,
 			disconnectedDialog: null as Promise<void> | null,
+			wallpaper: localStorage.getItem('wallpaper') != null,
 			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
 		};
 	},
@@ -972,6 +973,10 @@ export default Vue.extend({
 		margin: 0 auto;
 		min-width: 0;
 
+		&.wallpaper {
+			background: var(--wallpaperOverlay);
+		}
+
 		> main {
 			width: $main-width;
 			min-width: $main-width;
diff --git a/src/client/init.ts b/src/client/init.ts
index b013637f7f..69f071ddcf 100644
--- a/src/client/init.ts
+++ b/src/client/init.ts
@@ -136,8 +136,6 @@ document.body.innerHTML = '<div id="app"></div>';
 const os = new MiOS();
 
 os.init(async () => {
-	if (os.store.state.settings.wallpaper) document.documentElement.style.backgroundImage = `url(${os.store.state.settings.wallpaper})`;
-
 	if ('Notification' in window && os.store.getters.isSignedIn) {
 		// 許可を得ていなかったらリクエスト
 		if (Notification.permission === 'default') {
diff --git a/src/client/pages/settings/general.vue b/src/client/pages/settings/general.vue
index 6ebda9efeb..6b4825c7a9 100644
--- a/src/client/pages/settings/general.vue
+++ b/src/client/pages/settings/general.vue
@@ -2,12 +2,8 @@
 <section class="_card">
 	<div class="_title"><fa :icon="faCog"/> {{ $t('general') }}</div>
 	<div class="_content">
-		<mk-input type="file" @change="onWallpaperChange">
-			<span>{{ $t('wallpaper') }}</span>
-			<template #icon><fa :icon="faImage"/></template>
-			<template #desc v-if="wallpaperUploading">{{ $t('uploading') }}<mk-ellipsis/></template>
-		</mk-input>
-		<mk-button primary :disabled="$store.state.settings.wallpaper == null" @click="delWallpaper()">{{ $t('removeWallpaper') }}</mk-button>
+		<mk-button primary v-if="wallpaper == null" @click="setWallpaper">{{ $t('setWallpaper') }}</mk-button>
+		<mk-button primary v-else @click="wallpaper = null">{{ $t('removeWallpaper') }}</mk-button>
 	</div>
 	<div class="_content">
 		<mk-switch v-model="autoReload">
@@ -56,7 +52,8 @@ import MkSwitch from '../../components/ui/switch.vue';
 import MkSelect from '../../components/ui/select.vue';
 import MkRadio from '../../components/ui/radio.vue';
 import i18n from '../../i18n';
-import { apiUrl, langs } from '../../config';
+import { langs } from '../../config';
+import { selectFile } from '../../scripts/select-file';
 
 export default Vue.extend({
 	i18n,
@@ -74,17 +71,12 @@ export default Vue.extend({
 			langs,
 			lang: localStorage.getItem('lang'),
 			fontSize: localStorage.getItem('fontSize'),
-			wallpaperUploading: false,
+			wallpaper: localStorage.getItem('wallpaper'),
 			faImage, faCog
 		}
 	},
 
 	computed: {
-		wallpaper: {
-			get() { return this.$store.state.settings.wallpaper; },
-			set(value) { this.$store.dispatch('settings/set', { key: 'wallpaper', value }); }
-		},
-
 		autoReload: {
 			get() { return this.$store.state.device.autoReload; },
 			set(value) { this.$store.commit('device/set', { key: 'autoReload', value }); }
@@ -120,41 +112,25 @@ export default Vue.extend({
 				localStorage.setItem('fontSize', this.fontSize);
 			}
 			location.reload();
+		},
+
+		wallpaper() {
+			if (this.wallpaper == null) {
+				localStorage.removeItem('wallpaper');
+			} else {
+				localStorage.setItem('wallpaper', this.wallpaper);
+			}
+			location.reload();
 		}
 	},
 
 	methods: {
-		onWallpaperChange([file]) {
-			this.wallpaperUploading = true;
-
-			const data = new FormData();
-			data.append('file', file);
-			data.append('i', this.$store.state.i.token);
-
-			fetch(apiUrl + '/drive/files/create', {
-				method: 'POST',
-				body: data
-			})
-			.then(response => response.json())
-			.then(f => {
-				this.wallpaper = f.url;
-				this.wallpaperUploading = false;
-				document.documentElement.style.backgroundImage = `url(${this.$store.state.settings.wallpaper})`;
-			})
-			.catch(e => {
-				this.wallpaperUploading = false;
-				this.$root.dialog({
-					type: 'error',
-					text: e
-				});
+		setWallpaper(e) {
+			selectFile(this, e.currentTarget || e.target, null, false).then(file => {
+				this.wallpaper = file.url;
 			});
 		},
 
-		delWallpaper() {
-			this.wallpaper = null;
-			document.documentElement.style.backgroundImage = 'none';
-		},
-
 		onChangeAutoWatch(v) {
 			this.$root.api('i/update', {
 				autoWatch: v
diff --git a/src/client/pages/settings/theme.vue b/src/client/pages/settings/theme.vue
index ecedb83626..e8f11fb03c 100644
--- a/src/client/pages/settings/theme.vue
+++ b/src/client/pages/settings/theme.vue
@@ -35,7 +35,6 @@ export default Vue.extend({
 	
 	data() {
 		return {
-			wallpaperUploading: false,
 			faPalette
 		}
 	},
diff --git a/src/client/store.ts b/src/client/store.ts
index 485eb5b691..13722c1bb8 100644
--- a/src/client/store.ts
+++ b/src/client/store.ts
@@ -13,7 +13,6 @@ const defaultSettings = {
 	defaultNoteLocalOnly: false,
 	uploadFolder: null,
 	pastedFileName: 'yyyy-MM-dd HH-mm-ss [{{number}}]',
-	wallpaper: null,
 	memo: null,
 	reactions: ['👍', '❤️', '😆', '🤔', '😮', '🎉', '💢', '😥', '😇', '🍮'],
 };
diff --git a/src/client/theme.ts b/src/client/theme.ts
index 3ece30d47e..c446528f06 100644
--- a/src/client/theme.ts
+++ b/src/client/theme.ts
@@ -9,8 +9,8 @@ export type Theme = {
 	props: { [key: string]: string };
 };
 
-export const lightTheme: Theme = require('./themes/light.json5');
-export const darkTheme: Theme = require('./themes/dark.json5');
+export const lightTheme: Theme = require('./themes/_light.json5');
+export const darkTheme: Theme = require('./themes/_dark.json5');
 
 export const builtinThemes = [
 	lightTheme,
diff --git a/src/client/themes/dark.json5 b/src/client/themes/_dark.json5
similarity index 97%
rename from src/client/themes/dark.json5
rename to src/client/themes/_dark.json5
index 7cb95b4beb..76d078cf98 100644
--- a/src/client/themes/dark.json5
+++ b/src/client/themes/_dark.json5
@@ -46,6 +46,7 @@
 		inputBorder: '#959da2',
 		listItemHoverBg: 'rgba(255, 255, 255, 0.03)',
 		driveFolderBg: ':alpha<0.3<@accent',
+		wallpaperOverlay: 'rgba(0, 0, 0, 0.5)',
 		bonzsgfz: ':alpha<0<@bg',
 		pcncwizz: ':darken<2<@panel',
 		vocsgcxy: 'rgba(0, 0, 0, 0.5)',
diff --git a/src/client/themes/light.json5 b/src/client/themes/_light.json5
similarity index 97%
rename from src/client/themes/light.json5
rename to src/client/themes/_light.json5
index b72fcaa2e4..6156282ef7 100644
--- a/src/client/themes/light.json5
+++ b/src/client/themes/_light.json5
@@ -46,6 +46,7 @@
 		inputBorder: '#dae0e4',
 		listItemHoverBg: 'rgba(0, 0, 0, 0.03)',
 		driveFolderBg: ':alpha<0.3<@accent',
+		wallpaperOverlay: 'rgba(255, 255, 255, 0.5)',
 		bonzsgfz: ':alpha<0<@bg',
 		pcncwizz: ':darken<2<@panel',
 		vocsgcxy: 'rgba(255, 255, 255, 0.5)',
diff --git a/src/server/web/views/base.pug b/src/server/web/views/base.pug
index 94f5a8e0e2..20c3a64988 100644
--- a/src/server/web/views/base.pug
+++ b/src/server/web/views/base.pug
@@ -53,6 +53,11 @@ html
 				document.documentElement.classList.add('f-' + fontSize);
 			}
 
+			const wallpaper = localStorage.getItem('wallpaper');
+			if (wallpaper) {
+				document.documentElement.style.backgroundImage = `url(${wallpaper})`;
+			}
+
 	body
 		noscript: p
 			| JavaScriptを有効にしてください