diff --git a/.idea/.idea.osu.Desktop/.idea/misc.xml b/.idea/.idea.osu.Desktop/.idea/misc.xml
index 1d8c84d0af..4e1d56f4dd 100644
--- a/.idea/.idea.osu.Desktop/.idea/misc.xml
+++ b/.idea/.idea.osu.Desktop/.idea/misc.xml
@@ -1,5 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
+  <component name="SwUserDefinedSpecifications">
+    <option name="specTypeByUrl">
+      <map />
+    </option>
+  </component>
   <component name="com.jetbrains.rider.android.RiderAndroidMiscFileCreationComponent">
     <option name="ENSURE_MISC_FILE_EXISTS" value="true" />
   </component>
diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneScalingContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneScalingContainer.cs
new file mode 100644
index 0000000000..5d554719a5
--- /dev/null
+++ b/osu.Game.Tests/Visual/UserInterface/TestSceneScalingContainer.cs
@@ -0,0 +1,114 @@
+// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using NUnit.Framework;
+using osu.Framework.Allocation;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Primitives;
+using osu.Framework.Graphics.Shapes;
+using osu.Game.Configuration;
+using osu.Game.Graphics.Containers;
+using osuTK;
+using osuTK.Graphics;
+
+namespace osu.Game.Tests.Visual.UserInterface
+{
+    [TestFixture]
+    public class TestSceneScalingContainer : OsuTestScene
+    {
+        private OsuConfigManager osuConfigManager { get; set; }
+
+        private ScalingContainer scaling1;
+        private ScalingContainer scaling2;
+        private Box scaleTarget;
+
+        [BackgroundDependencyLoader]
+        private void load()
+        {
+            osuConfigManager = new OsuConfigManager(LocalStorage);
+
+            Dependencies.CacheAs(osuConfigManager);
+
+            Children = new Drawable[]
+            {
+                new Container
+                {
+                    RelativeSizeAxes = Axes.Both,
+                    Children = new Drawable[]
+                    {
+                        scaling1 = new ScalingContainer(ScalingMode.Everything)
+                        {
+                            Anchor = Anchor.Centre,
+                            Origin = Anchor.Centre,
+                            Scale = new Vector2(0.8f),
+                            Children = new Drawable[]
+                            {
+                                scaling2 = new ScalingContainer(ScalingMode.Everything)
+                                {
+                                    Anchor = Anchor.Centre,
+                                    Origin = Anchor.Centre,
+                                    Scale = new Vector2(0.8f),
+                                    Children = new Drawable[]
+                                    {
+                                        new Box
+                                        {
+                                            Colour = Color4.Purple,
+                                            RelativeSizeAxes = Axes.Both,
+                                        },
+                                        scaleTarget = new Box
+                                        {
+                                            Anchor = Anchor.Centre,
+                                            Origin = Anchor.Centre,
+                                            Colour = Color4.White,
+                                            Size = new Vector2(100),
+                                        },
+                                    }
+                                }
+                            }
+                        }
+                    }
+                },
+            };
+        }
+
+        [Test]
+        public void TestScaling()
+        {
+            AddStep("adjust scale", () => osuConfigManager.SetValue(OsuSetting.UIScale, 2f));
+
+            checkForCorrectness();
+
+            AddStep("adjust scale", () => osuConfigManager.SetValue(OsuSetting.UIScale, 0.5f));
+
+            checkForCorrectness();
+        }
+
+        private void checkForCorrectness()
+        {
+            Quad? scaling1LastQuad = null;
+            Quad? scaling2LastQuad = null;
+            Quad? scalingTargetLastQuad = null;
+
+            AddUntilStep("ensure dimensions don't change", () =>
+            {
+                if (scaling1LastQuad.HasValue && scaling2LastQuad.HasValue)
+                {
+                    // check inter-frame changes to make sure they match expectations.
+                    Assert.That(scaling1.ScreenSpaceDrawQuad.AlmostEquals(scaling1LastQuad.Value), Is.True);
+                    Assert.That(scaling2.ScreenSpaceDrawQuad.AlmostEquals(scaling2LastQuad.Value), Is.True);
+                }
+
+                scaling1LastQuad = scaling1.ScreenSpaceDrawQuad;
+                scaling2LastQuad = scaling2.ScreenSpaceDrawQuad;
+
+                // wait for scaling to stop.
+                bool scalingFinished = scalingTargetLastQuad.HasValue && scaleTarget.ScreenSpaceDrawQuad.AlmostEquals(scalingTargetLastQuad.Value);
+
+                scalingTargetLastQuad = scaleTarget.ScreenSpaceDrawQuad;
+
+                return scalingFinished;
+            });
+        }
+    }
+}
diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs
index 58d18e1b21..ca8b6f388f 100644
--- a/osu.Game/Graphics/Containers/ScalingContainer.cs
+++ b/osu.Game/Graphics/Containers/ScalingContainer.cs
@@ -21,6 +21,8 @@ namespace osu.Game.Graphics.Containers
     /// </summary>
     public class ScalingContainer : Container
     {
+        private const float duration = 500;
+
         private Bindable<float> sizeX;
         private Bindable<float> sizeY;
         private Bindable<float> posX;
@@ -82,6 +84,8 @@ namespace osu.Game.Graphics.Containers
             private readonly bool applyUIScale;
             private Bindable<float> uiScale;
 
+            private float currentScale = 1;
+
             public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true;
 
             public ScalingDrawSizePreservingFillContainer(bool applyUIScale)
@@ -95,14 +99,16 @@ namespace osu.Game.Graphics.Containers
                 if (applyUIScale)
                 {
                     uiScale = osuConfig.GetBindable<float>(OsuSetting.UIScale);
-                    uiScale.BindValueChanged(scaleChanged, true);
+                    uiScale.BindValueChanged(args => this.TransformTo(nameof(currentScale), args.NewValue, duration, Easing.OutQuart), true);
                 }
             }
 
-            private void scaleChanged(ValueChangedEvent<float> args)
+            protected override void Update()
             {
-                this.ScaleTo(new Vector2(args.NewValue), 500, Easing.Out);
-                this.ResizeTo(new Vector2(1 / args.NewValue), 500, Easing.Out);
+                Scale = new Vector2(currentScale);
+                Size = new Vector2(1 / currentScale);
+
+                base.Update();
             }
         }
 
@@ -140,8 +146,6 @@ namespace osu.Game.Graphics.Containers
 
         private void updateSize()
         {
-            const float duration = 500;
-
             if (targetMode == ScalingMode.Everything)
             {
                 // the top level scaling container manages the background to be displayed while scaling.