diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1d693e6b651508928b132d03f1d723a5317bf4a9..86c22859cf826535f46302ea52500fcd9205f1d3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -28,6 +28,9 @@ SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
   processes responsible for the respective parts of the finer grid. Then the indices on the coarser grid
   may differ from run to run.
 
+- Define `field_type` and `real_type` in `MultiTypeBlock[Matrix|Vector]` only if a common type of these
+  types exist over all blocks in the container. Otherwise it is defined as `Std::nonesuch`.
+
 ## Deprecations and removals
 
 - The deprecated CMake variables `SUPERLU_INCLUDE_DIRS`, `SUPERLU_LIBRARIES`,
diff --git a/dune/istl/multitypeblockmatrix.hh b/dune/istl/multitypeblockmatrix.hh
index 2477e157474e136c36b6212bef58f6231b7945ab..e2389d9ec6cd6a7567bc0a329ac33e082e8203a1 100644
--- a/dune/istl/multitypeblockmatrix.hh
+++ b/dune/istl/multitypeblockmatrix.hh
@@ -58,7 +58,27 @@ namespace Dune {
     /** \brief Type used for sizes */
     using size_type = std::size_t;
 
-    typedef typename FirstRow::field_type field_type;
+    /** \brief The type used for scalars
+     *
+     * Use the `std::common_type_t` of the `Args`' field_type and use `nonesuch` if no implementation of
+     * `std::common_type` is provided for the given `field_type` arguments.
+     */
+    using field_type = Std::detected_t<std::common_type_t,
+      typename FieldTraits<FirstRow>::field_type, typename FieldTraits<Args>::field_type...>;
+
+    /** \brief The type used for real values
+     *
+     * Use the `std::common_type_t` of the `Args`' real_type and use `nonesuch` if no implementation of
+     * `std::common_type` is provided for the given `real_type` arguments.
+     */
+    using real_type = Std::detected_t<std::common_type_t,
+      typename FieldTraits<FirstRow>::real_type, typename FieldTraits<Args>::real_type...>;
+
+    // make sure that we have an std::common_type: using an assertion produces a more readable error message
+    // than a compiler template instantiation error
+    static_assert ( sizeof...(Args) == 0 or
+                    not (std::is_same_v<field_type, Std::nonesuch> or std::is_same_v<real_type, Std::nonesuch>),
+        "No std::common_type implemented for the given field_type/real_type of the Args. Please provide an implementation and check that a FieldTraits class is present for your type.");
 
     /** \brief Return the number of matrix rows */
     static constexpr size_type N()
@@ -338,10 +358,9 @@ namespace Dune {
     //===== norms
 
     //! square of frobenius norm, need for block recursion
-    auto frobenius_norm2 () const
+    real_type frobenius_norm2 () const
     {
-      using field_type_00 = typename std::decay_t<decltype((*this)[Indices::_0][Indices::_0])>::field_type;
-      typename FieldTraits<field_type_00>::real_type sum=0;
+      real_type sum=0;
 
       auto rows = index_constant<N()>();
       Hybrid::forEach(Hybrid::integralRange(rows), [&](auto&& i) {
@@ -355,22 +374,20 @@ namespace Dune {
     }
 
     //! frobenius norm: sqrt(sum over squared values of entries)
-    typename FieldTraits<field_type>::real_type frobenius_norm () const
+    real_type frobenius_norm () const
     {
       return sqrt(frobenius_norm2());
     }
 
     //! Bastardized version of the infinity-norm / row-sum norm
-    auto infinity_norm () const
+    real_type infinity_norm () const
     {
-      using field_type_00 = typename std::decay_t<decltype((*this)[Indices::_0][Indices::_0])>::field_type;
       using std::max;
-      typename FieldTraits<field_type_00>::real_type norm=0;
+      real_type norm=0;
 
       auto rows = index_constant<N()>();
       Hybrid::forEach(Hybrid::integralRange(rows), [&](auto&& i) {
-
-        typename FieldTraits<field_type_00>::real_type sum=0;
+        real_type sum=0;
         auto cols = index_constant<MultiTypeBlockMatrix<FirstRow, Args...>::M()>();
         Hybrid::forEach(Hybrid::integralRange(cols), [&](auto&& j) {
           sum += (*this)[i][j].infinity_norm();
@@ -382,16 +399,14 @@ namespace Dune {
     }
 
     //! Bastardized version of the infinity-norm / row-sum norm
-    auto infinity_norm_real () const
+    real_type infinity_norm_real () const
     {
-      using field_type_00 = typename std::decay_t<decltype((*this)[Indices::_0][Indices::_0])>::field_type;
       using std::max;
-      typename FieldTraits<field_type_00>::real_type norm=0;
+      real_type norm=0;
 
       auto rows = index_constant<N()>();
       Hybrid::forEach(Hybrid::integralRange(rows), [&](auto&& i) {
-
-        typename FieldTraits<field_type_00>::real_type sum=0;
+        real_type sum=0;
         auto cols = index_constant<MultiTypeBlockMatrix<FirstRow, Args...>::M()>();
         Hybrid::forEach(Hybrid::integralRange(cols), [&](auto&& j) {
           sum += (*this)[i][j].infinity_norm_real();
@@ -412,7 +427,7 @@ namespace Dune {
   struct FieldTraits< MultiTypeBlockMatrix<Rows...> >
   {
     using field_type = typename MultiTypeBlockMatrix<Rows...>::field_type;
-    using real_type  = typename FieldTraits<field_type>::real_type;
+    using real_type  = typename MultiTypeBlockMatrix<Rows...>::real_type;
   };
 
 
diff --git a/dune/istl/multitypeblockvector.hh b/dune/istl/multitypeblockvector.hh
index a22b06561632da0f944bdefdc6ef1c347b7b0600..53987a35c56d946e740fd503bf8c5a6b7696c242 100644
--- a/dune/istl/multitypeblockvector.hh
+++ b/dune/istl/multitypeblockvector.hh
@@ -42,7 +42,7 @@ namespace Dune {
   struct FieldTraits< MultiTypeBlockVector<Args...> >
   {
     using field_type = typename MultiTypeBlockVector<Args...>::field_type;
-    using real_type  = typename FieldTraits<field_type>::real_type;
+    using real_type  = typename MultiTypeBlockVector<Args...>::real_type;
   };
   /**
       @}
@@ -81,10 +81,18 @@ namespace Dune {
      */
     using field_type = Std::detected_t<std::common_type_t, typename FieldTraits< std::decay_t<Args> >::field_type...>;
 
+    /** \brief The type used for real values
+     *
+     * Use the `std::common_type_t` of the `Args`' real_type and use `nonesuch` if no implementation of
+     * `std::common_type` is provided for the given `real_type` arguments.
+     */
+    using real_type = Std::detected_t<std::common_type_t, typename FieldTraits< std::decay_t<Args> >::real_type...>;
+
     // make sure that we have an std::common_type: using an assertion produces a more readable error message
     // than a compiler template instantiation error
-    static_assert ( sizeof...(Args) == 0 or not std::is_same_v<field_type, Std::nonesuch>,
-        "No std::common_type implemented for the given field_types of the Args. Please provide an implementation and check that a FieldTraits class is present for your type.");
+    static_assert ( sizeof...(Args) == 0 or
+                    not (std::is_same_v<field_type, Std::nonesuch> or std::is_same_v<real_type, Std::nonesuch>),
+        "No std::common_type implemented for the given field_type/real_type of the Args. Please provide an implementation and check that a FieldTraits class is present for your type.");
 
 
     /** \brief Return the number of non-zero vector entries
@@ -216,7 +224,7 @@ namespace Dune {
      */
     auto one_norm() const {
       using namespace Dune::Hybrid;
-      return accumulate(*this, typename FieldTraits<field_type>::real_type(0), [&](auto&& a, auto&& entry) {
+      return accumulate(*this, real_type(0), [&](auto&& a, auto&& entry) {
         return a + entry.one_norm();
       });
     }
@@ -225,31 +233,30 @@ namespace Dune {
      */
     auto one_norm_real() const {
       using namespace Dune::Hybrid;
-      return accumulate(*this, typename FieldTraits<field_type>::real_type(0), [&](auto&& a, auto&& entry) {
+      return accumulate(*this, real_type(0), [&](auto&& a, auto&& entry) {
         return a + entry.one_norm_real();
       });
     }
 
     /** \brief Compute the squared Euclidean norm
      */
-    typename FieldTraits<field_type>::real_type two_norm2() const {
+    real_type two_norm2() const {
       using namespace Dune::Hybrid;
-      return accumulate(*this, typename FieldTraits<field_type>::real_type(0), [&](auto&& a, auto&& entry) {
+      return accumulate(*this, real_type(0), [&](auto&& a, auto&& entry) {
         return a + entry.two_norm2();
       });
     }
 
     /** \brief Compute the Euclidean norm
      */
-    typename FieldTraits<field_type>::real_type two_norm() const {return sqrt(this->two_norm2());}
+    real_type two_norm() const {return sqrt(this->two_norm2());}
 
     /** \brief Compute the maximum norm
      */
-    typename FieldTraits<field_type>::real_type infinity_norm() const
+    real_type infinity_norm() const
     {
       using namespace Dune::Hybrid;
       using std::max;
-      using real_type = typename FieldTraits<field_type>::real_type;
 
       real_type result = 0.0;
       // Compute max norm tracking appearing nan values
@@ -276,11 +283,10 @@ namespace Dune {
 
     /** \brief Compute the simplified maximum norm (uses 1-norm for complex values)
      */
-    typename FieldTraits<field_type>::real_type infinity_norm_real() const
+    real_type infinity_norm_real() const
     {
       using namespace Dune::Hybrid;
       using std::max;
-      using real_type = typename FieldTraits<field_type>::real_type;
 
       real_type result = 0.0;
       // Compute max norm tracking appearing nan values