diff --git a/fsl/data/strings.py b/fsl/data/strings.py
index d6e99e50a97006a685b94b2539adb143b8e662d5..4f3673fd93687474de6c91872f6b4c67cf2ae179 100644
--- a/fsl/data/strings.py
+++ b/fsl/data/strings.py
@@ -506,6 +506,7 @@ properties = TypeDict({
     
     'VolumeOpts.displayRange'   : 'Display range',
     'VolumeOpts.clippingRange'  : 'Clipping range',
+    'VolumeOpts.centreRanges'   : 'Centre display/clipping ranges at 0',
     'VolumeOpts.cmap'           : 'Colour map',
     'VolumeOpts.invert'         : 'Invert colour map',
     'VolumeOpts.invertClipping' : 'Invert clipping range',
diff --git a/fsl/fsleyes/controls/overlaydisplaypanel.py b/fsl/fsleyes/controls/overlaydisplaypanel.py
index d1aa45915c58302789bdc88db5e0ea9f81831b6b..e8e44256a1d6cf654aad4d064715ffa52949699e 100644
--- a/fsl/fsleyes/controls/overlaydisplaypanel.py
+++ b/fsl/fsleyes/controls/overlaydisplaypanel.py
@@ -288,6 +288,7 @@ _DISPLAY_PROPS = td.TypeDict({
         props.Widget('cmap'),
         props.Widget('invert'),
         props.Widget('invertClipping'),
+        props.Widget('centreRanges'),
         props.Widget('displayRange',
                      showLimits=False,
                      slider=True,
diff --git a/fsl/fsleyes/displaycontext/volumeopts.py b/fsl/fsleyes/displaycontext/volumeopts.py
index 3f6702d11ce641fd000a60ddeb68dd8b7bee1a13..005cce6efcd3af6ca20a161842edd50a4040f81c 100644
--- a/fsl/fsleyes/displaycontext/volumeopts.py
+++ b/fsl/fsleyes/displaycontext/volumeopts.py
@@ -502,6 +502,13 @@ class VolumeOpts(ImageOpts):
     """
 
 
+    centreRanges = props.Boolean(default=False)
+    """If ``True``, the :attr:`displayRange` and :attr:`clippingRange` ranges
+    will be kept centred at zero. A change to the negative end of either range
+    will result in the positive end being changed, and vice versa.
+    """
+
+
     def __init__(self,
                  overlay,
                  display,
@@ -572,6 +579,9 @@ class VolumeOpts(ImageOpts):
             self   .addListener('displayRange',
                                 self.name,
                                 self.__displayRangeChanged)
+            self   .addListener('centreRanges',
+                                self.name,
+                                self.__centreRangesChanged) 
 
             # Because displayRange and bri/con are intrinsically
             # linked, it makes no sense to let the user sync/unsync
@@ -646,6 +656,11 @@ class VolumeOpts(ImageOpts):
 
         for peer in peers:
 
+            if not any((peer.display.isSyncedToParent('brightness'),
+                        peer.display.isSyncedToParent('contrast'),
+                        peer.        isSyncedToParent('displayRange'))):
+                continue
+
             if enable:
                 peer.display.enableListener('brightness',   peer.name)
                 peer.display.enableListener('contrast',     peer.name)
@@ -684,6 +699,9 @@ class VolumeOpts(ImageOpts):
         See :func:`.colourmaps.displayRangeToBricon`.
         """
 
+        if self.centreRanges:
+            return
+
         brightness, contrast = fslcm.displayRangeToBricon(
             (self.dataMin, self.dataMax),
             self.displayRange.x)
@@ -695,3 +713,83 @@ class VolumeOpts(ImageOpts):
         self.display.contrast   = contrast   * 100
 
         self.__toggleListeners(True)
+
+
+    def __centreRangesChanged(self, *a):
+        """Called when the :attr:`centreRanges` property changes. Configures
+        property listeners on the :attr:`clippingRange` and
+        :attr:`displayRange` properties.
+        """
+
+        if self.centreRanges:
+            self.display.disableProperty('brightness')
+            self.display.disableProperty('contrast')
+        else:
+            self.display.enableProperty('brightness')
+            self.display.enableProperty('contrast')
+
+        clipPVs = self.clippingRange.getPropertyValueList()
+        dispPVs = self.displayRange .getPropertyValueList()
+
+        if not self.centreRanges:
+            clipPVs[0].removeListener(self.name)
+            clipPVs[1].removeListener(self.name)
+            dispPVs[0].removeListener(self.name)
+            dispPVs[1].removeListener(self.name)
+        else:
+            clipPVs[0].addListener(self.name, self.__lowClippingChanged)
+            clipPVs[1].addListener(self.name, self.__highClippingChanged)
+            dispPVs[0].addListener(self.name, self.__lowDisplayChanged)
+            dispPVs[1].addListener(self.name, self.__highDisplayChanged)
+
+            self.__lowClippingChanged()
+            self.__lowDisplayChanged()
+
+
+    def __lowDisplayChanged(self, *a):
+        """If :attr:`centreRanges` is ``True``, this method is called whenever
+        the low :attr:`displayRange` value changes. It synchronises the high
+        value.
+        """
+        rangePVs = self.displayRange.getPropertyValueList()
+        
+        rangePVs[1].disableListener(self.name)
+        rangePVs[1].set(-rangePVs[0].get())
+        rangePVs[1].enableListener(self.name)
+
+        
+    def __highDisplayChanged(self, *a):
+        """If :attr:`centreRanges` is ``True``, this method is called whenever
+        the high :attr:`displayRange` value changes. It synchronises the low
+        value.
+        """ 
+        rangePVs = self.displayRange.getPropertyValueList()
+        
+        rangePVs[0].disableListener(self.name)
+        rangePVs[0].set(-rangePVs[1].get())
+        rangePVs[0].enableListener(self.name) 
+    
+
+    def __lowClippingChanged(self, *a):
+        """If :attr:`centreRanges` is ``True``, this method is called whenever
+        the low :attr:`clippingRange` value changes. It synchronises the high
+        value.
+        """ 
+        
+        clipPVs = self.clippingRange.getPropertyValueList()
+        
+        clipPVs[1].disableListener(self.name)
+        clipPVs[1].set(-clipPVs[0].get())
+        clipPVs[1].enableListener(self.name)
+
+    
+    def __highClippingChanged(self, *a):
+        """If :attr:`centreRanges` is ``True``, this method is called whenever
+        the high :attr:`clippingRange` value changes. It synchronises the low
+        value.
+        """ 
+        clipPVs = self.clippingRange.getPropertyValueList()
+        
+        clipPVs[0].disableListener(self.name)
+        clipPVs[0].set(-clipPVs[1].get())
+        clipPVs[0].enableListener(self.name)
diff --git a/fsl/fsleyes/tooltips.py b/fsl/fsleyes/tooltips.py
index 8d223ad81420d57ed94441f706bd49b994e13533..d60cf1c8ee6211ac5fe0f5f71bee8e90f4c760a4 100644
--- a/fsl/fsleyes/tooltips.py
+++ b/fsl/fsleyes/tooltips.py
@@ -67,6 +67,11 @@ properties = TypeDict({
                                    'voxels outside of the range are displayed.'
                                    'This option is useful for displaying '
                                    'statistic images.',
+    'VolumeOpts.centreRanges'    : 'If checked, the low and high values '
+                                   'of both the clipping and display '
+                                   'ranges will be yoked together, so '
+                                   'that both ranges stay centered at '
+                                   'zero.' ,
     'VolumeOpts.cmap'            : 'The colour map to use.',
     'VolumeOpts.interpolation'   : 'Interpolate the image data for display '
                                    'purposes. You can choose no  '