diff --git a/CMakeLists.txt b/CMakeLists.txt
index 560508e4aadb5974eb1adae2a7091207af67a9f5..2fc3da7724c2585f11fbe243f2fce775aafb9123 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -23,7 +23,11 @@ include(DuneMacros)
 
 # start a dune project with information from dune.module
 dune_project()
-dune_enable_all_packages(MODULE_LIBRARIES dumux_fmt dumux_parameters)
+if (DUMUX_HAVE_STD_FORMAT)
+  dune_enable_all_packages(MODULE_LIBRARIES dumux_parameters)
+else()
+  dune_enable_all_packages(MODULE_LIBRARIES dumux_fmt dumux_parameters)
+endif()
 
 # enforce C++-17
 dune_require_cxx_standard(MODULE "DuMuX" VERSION 17)
diff --git a/cmake/modules/DumuxMacros.cmake b/cmake/modules/DumuxMacros.cmake
index b679f21c367e15f39a3f260718d9c9233fb547a8..547ce7b4cf0c37c5ba3e4d2a2e5e5d4be95dc717 100644
--- a/cmake/modules/DumuxMacros.cmake
+++ b/cmake/modules/DumuxMacros.cmake
@@ -17,6 +17,13 @@ find_package(PVPython QUIET)
 find_package(Kokkos QUIET)
 include(AddKokkosFlags)
 
+# test if compiler supports std::format
+check_cxx_symbol_exists(
+  "__cpp_lib_format"
+  "format"
+  DUMUX_HAVE_STD_FORMAT
+)
+
 # possibly link against TBB
 # even if an older version is found
 # otherwise we get linker errors
diff --git a/dumux/common/dumuxmessage.hh b/dumux/common/dumuxmessage.hh
index dce567615f884218157c215301cbe48f005d0807..937da2af35b6d9417cb52f2aed3b39fd67b911fa 100644
--- a/dumux/common/dumuxmessage.hh
+++ b/dumux/common/dumuxmessage.hh
@@ -170,9 +170,11 @@ public:
             break;
             case 12:
                 if (firstCall)
-                    std::cout << Fmt::format("  ┌{0:─^{2}}┐\n"
-                                             "  │{1: ^{2}}│\n"
-                                             "  └{0:─^{2}}┘\n", "", Fmt::format("DuMuX {} \u2661", DUMUX_VERSION), 20);
+                {
+                    std::cout << "  ┌──────────────────┐" << std::endl;
+                    std::cout << Fmt::format("  │{:^20}│", Fmt::format("DuMuX {} \u2661", DUMUX_VERSION)) << std::endl;
+                    std::cout << "  └──────────────────┘" << std::endl;
+                }
                 else
                     std::cout << "\n" << std::endl;
             break;
diff --git a/dumux/io/format.hh b/dumux/io/format.hh
index dcdd10d04d7415a4495243967f75b4c39287517d..5a8b005623fe3dfed66e42f6ad381f06b48e4f6c 100644
--- a/dumux/io/format.hh
+++ b/dumux/io/format.hh
@@ -30,12 +30,27 @@
 #ifndef DUMUX_IO_FORMAT_HH
 #define DUMUX_IO_FORMAT_HH
 
+#if __has_include(<format>) // cppcheck-suppress preprocessorErrorDirective
+#include <format>
+#endif
+
 #include <dumux/io/format/fmt/format.h>
 #include <dumux/io/format/fmt/ranges.h>
 
 //! Formatting tools in the style of std::format (C++20)
 namespace Dumux::Fmt {
 
+#if __cpp_lib_format
+// use std::format from C++20
+using std::format;
+using std::format_to;
+using std::format_to_n;
+using std::formatted_size;
+using std::vformat;
+using std::vformat_to;
+using std::make_format_args;
+#else
+// use fallback fmt library
 using Dumux::Detail::fmt::format;
 using Dumux::Detail::fmt::format_to;
 using Dumux::Detail::fmt::format_to_n;
@@ -43,6 +58,7 @@ using Dumux::Detail::fmt::formatted_size;
 using Dumux::Detail::fmt::vformat;
 using Dumux::Detail::fmt::vformat_to;
 using Dumux::Detail::fmt::make_format_args;
+#endif
 
 } // end namespace Dumux::Fmt
 
diff --git a/dumux/io/format/fmt/CMakeLists.txt b/dumux/io/format/fmt/CMakeLists.txt
index 9916619e8325d3407c5b5022ee6191771c71b1f8..cc03eac229e21097167bbba1b16d42925b0adf42 100644
--- a/dumux/io/format/fmt/CMakeLists.txt
+++ b/dumux/io/format/fmt/CMakeLists.txt
@@ -1,5 +1,7 @@
-dune_library_add_sources(dumux_fmt SOURCES format.cc)
+if (NOT DUMUX_HAVE_STD_FORMAT)
+  dune_library_add_sources(dumux_fmt SOURCES format.cc)
 
-file(GLOB FMT_HEADERS *.h)
-install(FILES ${FMT_HEADERS}
-        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dumux/io/format/fmt)
+  file(GLOB FMT_HEADERS *.h)
+  install(FILES ${FMT_HEADERS} format.cc
+          DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dumux/io/format/fmt)
+endif()
diff --git a/test/geometry/test_distance.cc b/test/geometry/test_distance.cc
index b61d11370f0bfed959fa5ab9782805c2297a67e4..8d6a93b4a897f95a63e38f5fc863ca4a7ecf4968 100644
--- a/test/geometry/test_distance.cc
+++ b/test/geometry/test_distance.cc
@@ -225,10 +225,10 @@ void runTests()
                 const auto& expectedCenter = firstTriangle.center();
                 const auto expectedRadius = (firstTriangle.corner(0) - expectedCenter).two_norm();
                 if ((sphere.center() - expectedCenter).two_norm() > 1e-12*expectedRadius)
-                    DUNE_THROW(Dune::InvalidStateException, Fmt::format(
-                        "Wrong circumsphere center. Expected {}, got {}.",
-                        expectedCenter, sphere.center()
-                    ));
+                    DUNE_THROW(Dune::InvalidStateException,
+                        "Wrong circumsphere center. Expected "
+                        << expectedCenter << " got " << sphere.center()
+                    );
 
                 if (Dune::FloatCmp::ne(sphere.radius(), expectedRadius))
                     DUNE_THROW(Dune::InvalidStateException, Fmt::format(