Merge pull request #3222 from SillyTavern/bg-fitting Add background image fitting options

28c7dbbe1bb6c3d8797c50fa851a54d284471cec

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
3 files changed, +65 -1Ignore whitespace
public/index.html+7 -0
@@ -4713,6 +4713,13 @@
47134713 Background Image
47144714 </h3>
47154715 <input id="bg-filter" data-i18n="[placeholder]Filter" placeholder="Filter" class="text_pole flex1" type="search" />
4716+ <select id="background_fitting" class="text_pole" data-i18n="[title]Background Fitting" title="Background Fitting">
4717+ <option value="classic" data-i18n="Classic">Classic</option>
4718+ <option value="cover" data-i18n="Cover">Cover</option>
4719+ <option value="contain" data-i18n="Contain">Contain</option>
4720+ <option value="stretch" data-i18n="Stretch">Stretch</option>
4721+ <option value="center" data-i18n="Center">Center</option>
4722+ </select>
47164723 <div id="auto_background" class="menu_button menu_button_icon" data-i18n="[title]Automatically select a background based on the chat context" title="Automatically select a background based on the chat context.">
47174724 <i class="fa-solid fa-wand-magic"></i>
47184725 <span data-i18n="Auto-select">Auto-select</span>
public/scripts/backgrounds.js+23 -0
@@ -12,6 +12,7 @@ const LIST_METADATA_KEY = 'chat_backgrounds';
1212export let background_settings = {
1313 name: '__transparent.png',
1414 url: generateUrlParameter('__transparent.png', false),
15+ fitting: 'classic',
1516};
1617
1718export function loadBackgroundSettings(settings) {
@@ -19,7 +20,12 @@ export function loadBackgroundSettings(settings) {
1920 if (!backgroundSettings || !backgroundSettings.name || !backgroundSettings.url) {
2021 backgroundSettings = background_settings;
2122 }
23+ if (!backgroundSettings.fitting) {
24+ backgroundSettings.fitting = 'classic';
25+ }
2226 setBackground(backgroundSettings.name, backgroundSettings.url);
27+ setFittingClass(backgroundSettings.fitting);
28+ $('#background_fitting').val(backgroundSettings.fitting);
2329}
2430
2531/**
@@ -470,6 +476,18 @@ function highlightNewBackground(bg) {
470476 flashHighlight(newBg);
471477}
472478
479+/**
480+ * Sets the fitting class for the background element
481+ * @param {string} fitting Fitting type
482+ */
483+function setFittingClass(fitting) {
484+ const backgrounds = $('#bg1, #bg_custom');
485+ backgrounds.toggleClass('cover', fitting === 'cover');
486+ backgrounds.toggleClass('contain', fitting === 'contain');
487+ backgrounds.toggleClass('stretch', fitting === 'stretch');
488+ backgrounds.toggleClass('center', fitting === 'center');
489+}
490+
473491function onBackgroundFilterInput() {
474492 const filterValue = String($(this).val()).toLowerCase();
475493 $('#bg_menu_content > div').each(function () {
@@ -510,4 +528,9 @@ export function initBackgrounds() {
510528 helpString: 'Automatically changes the background based on the chat context using the AI request prompt',
511529 }));
512530
531+ $('#background_fitting').on('input', function () {
532+ background_settings.fitting = String($(this).val());
533+ setFittingClass(background_settings.fitting);
534+ saveSettingsDebounced();
535+ });
513536}
public/style.css+35 -1
@@ -141,7 +141,7 @@ body {
141141 height: 100dvh;
142142 /*defaults as 100%, then reassigned via JS as pixels, will work on PC and Android*/
143143 /*height: calc(var(--doc-height) - 1px);*/
144144 background-color: var(--greyCAIbgSmartThemeBlurTintColor);
145145 background-repeat: no-repeat;
146146 background-attachment: fixed;
147147 background-size: cover;
@@ -519,6 +519,40 @@ hr {
519519 transition: background-image 0.5s ease-in-out;
520520}
521521
522+/* Background fitting options */
523+#background_fitting {
524+ max-width: 6em;
525+}
526+
527+/* Fill/Cover - scales to fill width while maintaining aspect ratio */
528+#bg1.cover,
529+#bg_custom.cover {
530+ background-size: cover;
531+ background-position: center;
532+}
533+
534+/* Fit/Contain - shows entire image maintaining aspect ratio */
535+#bg1.contain,
536+#bg_custom.contain {
537+ background-size: contain;
538+ background-position: center;
539+ background-repeat: no-repeat;
540+}
541+
542+/* Stretch - stretches to fill entire space */
543+#bg1.stretch,
544+#bg_custom.stretch {
545+ background-size: 100% 100%;
546+}
547+
548+/* Center - centers without scaling */
549+#bg1.center,
550+#bg_custom.center {
551+ background-size: auto;
552+ background-position: center;
553+ background-repeat: no-repeat;
554+}
555+
522556body.reduced-motion #bg1,
523557body.reduced-motion #bg_custom {
524558 transition: none;