diff --git a/assets/js/theme/blocks/campus.js b/assets/js/theme/blocks/campus.js
new file mode 100644
index 0000000000000000000000000000000000000000..bb9ace023d300962c10ca19c5ff6d611b2c04221
--- /dev/null
+++ b/assets/js/theme/blocks/campus.js
@@ -0,0 +1,63 @@
+const campusMap = document.querySelector('.campus-map');
+const dom = document.querySelector('main');
+class CampusMap {
+    constructor (dom, campusMap) {
+        this.dom = dom;
+        this.map = campusMap;
+        this.init();
+    }
+
+    init () {
+        this.markers = [];
+        this.setMap = false;
+        this.content = this.map.querySelector('.map');
+        this.campus = this.content.querySelector('.campus');
+        let map = L.map(this.content, {
+            scrollWheelZoom: false
+        });
+        this.geoloc = {
+            latitude: parseFloat(this.campus.getAttribute('data-latitude')),
+            longitude: parseFloat(this.campus.getAttribute('data-longitude'))
+        };
+        this.classHidden = 'hidden';
+
+        this.themeMarker = L.icon({
+            iconUrl: this.content.getAttribute('data-marker-icon') || '/assets/images/map-marker.svg',
+            iconSize: [17, 26]
+        });
+        
+        if (Boolean(this.geoloc.latitude) && Boolean(this.geoloc.longitude)) {
+            let mapLocation = [this.geoloc.latitude, this.geoloc.longitude];
+            let marker = new L.marker(mapLocation, {
+                icon: this.themeMarker
+            });
+
+            const popup = new L.Popup({'autoClose':false, 'closeButton':false, 'maxWidth': 1000});
+            popup.setLatLng(mapLocation);
+            popup.setContent(this.campus);
+            popup.openOn(map);
+            marker.addTo(map).bindPopup(popup);
+            this.markers.push(marker);
+            this.setMap = true;
+            this.listen(map);
+            this.getMapBounds(map);
+            this.dom.classList.add("page-with-map");
+        }
+    }
+
+    listen (map) {
+        L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
+            maxZoom: 19,
+            attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
+        }).addTo(map);
+    }
+
+    getMapBounds (map) {
+        this.group = L.featureGroup(this.markers).addTo(map);
+        map.fitBounds(this.group.getBounds());
+    }
+}
+
+if (campusMap) {
+    new CampusMap(dom, campusMap);
+}
\ No newline at end of file
diff --git a/assets/js/theme/index.js b/assets/js/theme/index.js
index ff242d719855e0f272109f25bf5cbaf63fcf788f..949ab10918fcb92eec7c9d7c3d1b3d7e4886355a 100644
--- a/assets/js/theme/index.js
+++ b/assets/js/theme/index.js
@@ -11,3 +11,4 @@ import './blocks/keyFigures';
 import './blocks/organizations';
 import './blocks/draggableBlocks.js';
 import './blocks/videos.js';
+import './blocks/campus.js';
\ No newline at end of file
diff --git a/assets/sass/_theme/design-system/layout.sass b/assets/sass/_theme/design-system/layout.sass
index f17fe9c37c4910ad895297bc2d7677e247c011f0..66437c67798a3f66e5c65cf784e07e5ee8f44096 100644
--- a/assets/sass/_theme/design-system/layout.sass
+++ b/assets/sass/_theme/design-system/layout.sass
@@ -30,7 +30,7 @@ body
     //         transition-duration: 0s !important
 
 main
-    &:not(.page-with-blocks)
+    &:not(.page-with-blocks, .page-with-map)
         padding-bottom: $spacing-5
 
 iframe
diff --git a/assets/sass/_theme/sections/diplomas.sass b/assets/sass/_theme/sections/diplomas.sass
index 6e7e4c7175b89b4eea7eb8499c82a8d835c3dbd6..3e44257841b60ea5a796de5f8e74c7a1b5f8a6b5 100644
--- a/assets/sass/_theme/sections/diplomas.sass
+++ b/assets/sass/_theme/sections/diplomas.sass
@@ -192,4 +192,51 @@ ul.diplomas
                         position: relative
                         margin-left: $spacing-1
                     + p
-                        margin-top: $spacing-2
\ No newline at end of file
+                        margin-top: $spacing-2
+
+.locations__term
+    ul.diplomas
+        > li
+            > a
+                border-bottom: none
+                &::after
+                    align-self: end
+                    margin-left: $spacing-2
+                    position: static
+            .content
+                grid-template-columns: repeat(1, 1fr)
+                grid-gap: 0
+                ol.programs
+                    > li
+                        align-items: flex-start
+                        display: flex
+                        flex-direction: column-reverse
+                        @include media-breakpoint-up(md)
+                            flex-direction: row
+                            gap: var(--grid-gutter)
+                        &:not(:first-child)
+                            border-top: 1px solid var(--color-border)
+                            padding-top: $spacing-3
+                        .program-content
+                            width: 100%
+                            @include media-breakpoint-up(xl)
+                                width: columns(8)        
+                            > a
+                                @include icon(arrow-right, after)
+                                    align-self: end
+                                    margin-left: $spacing-1
+                            .description
+                                padding-top: $spacing-2 
+                        .media
+                            padding-bottom: $spacing-2
+                            width: columns(6)
+                            @include media-breakpoint-up(md)
+                                padding-bottom: 0
+                                width: columns(4)
+                            @include media-breakpoint-up(xl)
+                                width: columns(2)
+                            img
+                                aspect-ratio: 1
+                                display: block
+                                height: 100%
+                                object-fit: cover
\ No newline at end of file
diff --git a/assets/sass/_theme/sections/locations.sass b/assets/sass/_theme/sections/locations.sass
index a556be5fff50751699508aff0c7bb350e678e43b..724dec00bfe7a9783cd2dba43aad9c4f1a50662c 100644
--- a/assets/sass/_theme/sections/locations.sass
+++ b/assets/sass/_theme/sections/locations.sass
@@ -26,14 +26,14 @@
         @include stretched-link
         text-decoration: none
     .media
-        order: -1
         aspect-ratio: 1.3
         background: var(--color-background-alt)
+        order: -1
         img
             display: block
-            width: 100%
             height: 100%
             object-fit: cover
+            width: 100%
     &-title
         @include icon(arrow, after, true)
         @include hover-translate-icon(after)
@@ -42,4 +42,59 @@
     @include media-breakpoint-down(desktop)
         .media
             margin-left: var(--grid-gutter-negative)
-            margin-right: var(--grid-gutter-negative)
\ No newline at end of file
+            margin-right: var(--grid-gutter-negative)
+
+.campus-map
+    .map
+        height: 300px
+        z-index: 1
+        @include media-breakpoint-up(desktop)
+            height: 500px
+        > .campus,
+        .leaflet-popup-tip-container
+            display: none
+        .leaflet-tile-pane
+            filter: grayscale(1)
+        .leaflet-popup
+            &::after //crée un triangle en css (https://outils-css.aliasdmc.fr/generateur-de-triangles-css.php)
+                border-left: 10px solid transparent
+                border-right: 10px solid transparent
+                border-top: 15px solid var(--color-accent)
+                content: ''
+                display: block
+                height: 0
+                margin: 0 auto
+                width: 0
+            &-content
+                background-color: var(--color-accent)
+                color: var(--color-background)
+                height: 100%
+                margin: 0
+                min-width: min-content
+                width: auto !important // corrige la width appliquée en js par leaflet
+                .campus
+                    align-items: center
+                    display: flex
+                    .campus-content
+                        order: 2 
+                        padding: 0 $spacing-3
+                        span,
+                        .campus-title
+                            display: block
+                            margin: 0 // Cancel leaflet default style
+                            width: max-content
+                    .media
+                        aspect-ratio: 1
+                        display: block
+                        width: $spacing-6
+                        margin-bottom: 0
+                        order: 1
+                        img
+                            display: block
+                            height: 100%
+                            object-fit: cover
+                &-wrapper
+                    border-radius: 0
+                    padding: 0
+                    box-shadow: none
+                    overflow: hidden
\ No newline at end of file
diff --git a/config.yaml b/config.yaml
index 8935646a018c2ce942a7f9abd2709e53a50a42cd..e921187b48c813846559b4bd603d015e7f36dcc6 100644
--- a/config.yaml
+++ b/config.yaml
@@ -324,6 +324,10 @@ params:
           mobile:   351x168
           tablet:   456x219
           desktop:  856x410
+        item:
+          mobile:   350
+          tablet:   450
+          desktop:  600
       publications:
         hero:
           mobile:   400
@@ -350,4 +354,8 @@ params:
         item:
           mobile:   350
           tablet:   450
-          desktop:  900
\ No newline at end of file
+          desktop:  900
+        map: 
+          mobile:   150
+          tablet:   150
+          desktop:  150
\ No newline at end of file
diff --git a/layouts/locations/term.html b/layouts/locations/term.html
index 647b1bfffcfd6d5192e695d639290205be76b875..99a40a47cce07babc0dfd8c570499d1c93b4f48a 100644
--- a/layouts/locations/term.html
+++ b/layouts/locations/term.html
@@ -25,9 +25,12 @@
           {{ end }}
         {{ end }}
 
-        {{ partial "diplomas/diplomas.html" ( dict "diplomas" $diplomas ) }}
+        {{ partial "locations/diplomas.html" ( dict "diplomas" $diplomas ) }}
       {{ end }}
       {{ partial "commons/pagination.html" . }}
     </div>
   </div>
-{{ end }}
+  {{ if and .Params.contact_details.geolocation.longitude .Params.contact_details.geolocation.latitude }}
+    {{ partial "locations/map.html" . }}
+  {{ end }}
+{{ end }}
\ No newline at end of file
diff --git a/layouts/partials/footer/js.html b/layouts/partials/footer/js.html
index ed7569d424c8c31efb3bb791cb3b37b90f7143ca..3a52b13b7fb15360f447526115765a0e1fb758f6 100644
--- a/layouts/partials/footer/js.html
+++ b/layouts/partials/footer/js.html
@@ -22,6 +22,9 @@
       {{ $isSplideNeed = true }}
     {{ end }}
   {{ end }}
+<!-- check if map needed  -->
+{{ else if .Params.contact_details.geolocation }} 
+  {{ $isLeafletNeeded = true }}
 {{ end }}
 
 {{ if $isSplideNeed }}
diff --git a/layouts/partials/locations/diplomas.html b/layouts/partials/locations/diplomas.html
new file mode 100644
index 0000000000000000000000000000000000000000..88da267829752836ff2d3336b6615f99ef9158d5
--- /dev/null
+++ b/layouts/partials/locations/diplomas.html
@@ -0,0 +1,17 @@
+{{ $diplomas := .diplomas }}
+<ul class="diplomas">
+  {{ range $diplomas }}
+    <li>
+      <a href="{{ .Permalink }}" aria-label="{{ i18n "commons.more_aria" (dict "Title" .Title) }}">
+        {{- partial "PrepareHTML" .Title -}}
+      </a>
+      <div class="content">
+        <ol class="programs">
+          {{- range .Params.programs -}}
+            {{- template "partials/locations/template-program.html" . -}}
+          {{- end -}}
+        </ol>
+      </div>
+    </li>
+  {{ end }}
+</ul>
\ No newline at end of file
diff --git a/layouts/partials/locations/map.html b/layouts/partials/locations/map.html
new file mode 100644
index 0000000000000000000000000000000000000000..52846bae15240813c0f555216b252f197f3c918e
--- /dev/null
+++ b/layouts/partials/locations/map.html
@@ -0,0 +1,38 @@
+<div class="campus-map">
+  <div class="map" data-marker-icon="{{ "/assets/images/map-marker.svg" }}">
+    <article class="campus" data-longitude="{{ .Params.contact_details.geolocation.longitude }}"data-latitude="{{ .Params.contact_details.geolocation.latitude }}">
+      {{ $title := "" }}
+      {{ if .Params.title }}
+        <div class="campus-content">
+          {{ $title = partial "PrepareHTML" .Params.title -}}
+          <p class="campus-title">
+            {{- if and .Params.url .Params.with_link }}
+              <a href="{{ .Params.url }}" {{ if .external }} target="_blank" rel="noopener" {{ end }} title="{{ safeHTML (i18n "commons.link.blank_aria" (dict "Title" $title)) }}">
+            {{ end -}}
+            {{- $title -}}
+            {{- if .Params.url }}
+              </a>
+            {{ end -}}
+          </p>
+          {{ with .Params.contact_details }}
+            <span>{{ .address.value }}</span>
+            <span>
+              {{ .zipcode.value }}
+              {{ .city.value }}
+            </span>
+          {{ end }}
+        </div>
+      {{ end -}}
+      {{- if .Params.image -}}
+        <div class="media">
+          {{- partial "commons/image.html"
+            (dict
+              "image"  .Params.image
+              "alt"    $title
+              "sizes"  site.Params.image_sizes.sections.locations.map
+             ) -}}
+        </div>
+      {{- end -}}
+    </article>
+  </div>
+</div>
diff --git a/layouts/partials/locations/template-program.html b/layouts/partials/locations/template-program.html
new file mode 100644
index 0000000000000000000000000000000000000000..2d29238b932e2a701d7e6f001930d2ff9ac5ae2e
--- /dev/null
+++ b/layouts/partials/locations/template-program.html
@@ -0,0 +1,20 @@
+{{ $program := site.GetPage (printf "/programs%s" .slug) }}
+<li>
+  <div class="program-content">
+    <a href="{{ .path }}" title="{{ safeHTML (i18n "commons.more_aria" (dict "Title" .label)) }}">
+      {{- partial "PrepareHTML" .label -}}
+    </a>
+    <div class="description">
+      {{- $program.Params.summary }}
+    </div>
+  </div>
+  <div class="media">
+    {{- if $program.Params.image -}}
+      {{- partial "commons/image.html"
+        (dict
+            "image"    $program.Params.image
+            "sizes"    site.Params.image_sizes.sections.programs.item
+        ) -}}
+    {{- end -}}
+  </div>
+</li>