diff --git a/src/app/components/field-set/field-set.component.html b/src/app/components/field-set/field-set.component.html
index b87bbe724705e0503c85490c8e4cbdabb19188d8..0dea7034b85852407812e4aea01b96e592239fc6 100644
--- a/src/app/components/field-set/field-set.component.html
+++ b/src/app/components/field-set/field-set.component.html
@@ -20,7 +20,8 @@
 
 <mat-card-content>
     <ng-template ngFor let-p [ngForOf]="fields">
-        <param-field-line *ngIf="isInputField(p)" [param]=p (radio)=onRadioClick($event) (valid)=onParamLineValid() (inputChange)=onInputChange()>
+        <param-field-line *ngIf="isInputField(p)" [param]=p (radio)=onRadioClick($event) (valid)=onParamLineValid()
+            (inputChange)=onInputChange() (tabPressed)="onTabPressed($event)">
         </param-field-line>
 
         <select-field-line *ngIf="isSelectField(p)" [_select]=p>
diff --git a/src/app/components/field-set/field-set.component.ts b/src/app/components/field-set/field-set.component.ts
index 1541cba64a890778294eeaa5309ece21a2204796..bb3c51de86b46f5a931fee54cf659e553c1b8fa4 100644
--- a/src/app/components/field-set/field-set.component.ts
+++ b/src/app/components/field-set/field-set.component.ts
@@ -117,6 +117,10 @@ export class FieldSetComponent implements DoCheck {
     @Output()
     private radio = new EventEmitter<any>();
 
+    /** événement signalant un appui sur TAB ou SHIFT+TAB */
+    @Output()
+    protected tabPressed = new EventEmitter<any>();
+
     private hasRadioFix(): boolean {
         if (this._fieldSet.hasInputs) {
             switch (this._fieldSet.getInput(0).radioConfig) {
@@ -209,6 +213,13 @@ export class FieldSetComponent implements DoCheck {
         this.validChange.emit();
     }
 
+    /**
+     * Renvoie l'événement au composant du dessus
+     */
+    public onTabPressed(event) {
+        this.tabPressed.emit(event);
+    }
+
     public ngDoCheck() {
         this.updateValidity();
     }
diff --git a/src/app/components/fieldset-container/fieldset-container.component.html b/src/app/components/fieldset-container/fieldset-container.component.html
index 3bb2f5d4c370f52dd13b9ceabe74bea170bf0fe8..c2f75e4f19ef29b671ec12f24afabd08b67f648b 100644
--- a/src/app/components/fieldset-container/fieldset-container.component.html
+++ b/src/app/components/fieldset-container/fieldset-container.component.html
@@ -8,6 +8,7 @@
     <field-set *ngFor="let fs of fieldsets" class="fieldset-inner" [fieldSet]=fs
         (radio)=onRadioClick($event) (validChange)=onFieldsetValid() (inputChange)=onInputChange()
         (addFieldset)=onAddFieldset($event) (removeFieldset)=onRemoveFieldset($event)
-        (moveFieldsetDown)=onMoveFieldsetDown($event) (moveFieldsetUp)=onMoveFieldsetUp($event)>
+        (moveFieldsetDown)=onMoveFieldsetDown($event) (moveFieldsetUp)=onMoveFieldsetUp($event)
+        (tabPressed)="onTabPressed($event)">
     </field-set>
 </mat-card-content>
diff --git a/src/app/components/fieldset-container/fieldset-container.component.ts b/src/app/components/fieldset-container/fieldset-container.component.ts
index 15ca4d3e33a0c30d819d8b731ed32d8d20ffec51..b5e7be12e51d7e97caa1ee80e71024378c4e9522 100644
--- a/src/app/components/fieldset-container/fieldset-container.component.ts
+++ b/src/app/components/fieldset-container/fieldset-container.component.ts
@@ -60,6 +60,10 @@ export class FieldsetContainerComponent implements DoCheck, AfterViewInit {
     @Output()
     private inputChange = new EventEmitter();
 
+    /** événement signalant un appui sur TAB ou SHIFT+TAB */
+    @Output()
+    protected tabPressed = new EventEmitter<any>();
+
     private addStructure(after?: FieldSet) {
         if (after) {
             this._container.addFromTemplate(0, after.indexAsKid());
@@ -204,4 +208,11 @@ export class FieldsetContainerComponent implements DoCheck, AfterViewInit {
         const form = this._container.parent as FormulaireDefinition;
         form.moveFieldsetDown(fs);
     }
+
+    /**
+     * Renvoie l'événement au composant du dessus
+     */
+    public onTabPressed(event) {
+        this.tabPressed.emit(event);
+    }
 }
diff --git a/src/app/components/generic-calculator/calculator.component.html b/src/app/components/generic-calculator/calculator.component.html
index a714e0be4ec9b5bac39a194d92fbecfded9932f2..27eb0116b79bdf0a9ae47fa11d3623aa758914f1 100644
--- a/src/app/components/generic-calculator/calculator.component.html
+++ b/src/app/components/generic-calculator/calculator.component.html
@@ -32,10 +32,14 @@
                 <!-- chapitres -->
                 <mat-card id="calc-card-field-sets" fxFlex.gt-xs="1 0 400px" fxFlex.lt-sm="1 0 300px">
                     <ng-template ngFor let-fe [ngForOf]="formElements">
-                        <field-set *ngIf="isFieldset(fe)" [style.display]="getFieldsetStyleDisplay(fe.id)" [fieldSet]=fe (radio)=onRadioClick($event)
-                            (validChange)=OnFieldsetValid() (inputChange)=onInputChange()></field-set>
+                        <field-set *ngIf="isFieldset(fe)" [style.display]="getFieldsetStyleDisplay(fe.id)" [fieldSet]=fe
+                            (radio)=onRadioClick($event) (validChange)=OnFieldsetValid() (inputChange)=onInputChange()
+                            (tabPressed)="onTabPressed($event)">
+                        </field-set>
 
-                        <fieldset-container *ngIf="isFieldsetContainer(fe)" [_container]=fe (radio)=onRadioClick($event) (validChange)=onFieldsetContainerValid()></fieldset-container>
+                        <fieldset-container *ngIf="isFieldsetContainer(fe)" [_container]=fe (radio)=onRadioClick($event)
+                            (validChange)=onFieldsetContainerValid() (tabPressed)="onTabPressed($event)">
+                        </fieldset-container>
                     </ng-template>
 
                     <mat-card-actions>
diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts
index 31842b9690c9e477dfd037eebcbe24686421144d..d7a267bb7d34f8fc668b9263a7cfd371eccb717a 100644
--- a/src/app/components/generic-calculator/calculator.component.ts
+++ b/src/app/components/generic-calculator/calculator.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit, DoCheck, OnDestroy, ViewChild, ViewChildren, QueryList, AfterViewChecked } from "@angular/core";
+import { Component, OnInit, DoCheck, OnDestroy, ViewChild, ViewChildren, QueryList, AfterViewChecked, ElementRef, Renderer2 } from "@angular/core";
 import { ActivatedRoute, Router } from "@angular/router";
 
 import { Observer, Session, ParamValueMode } from "jalhyd";
@@ -98,7 +98,9 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit,
     constructor(
         private route: ActivatedRoute,
         private router: Router,
-        private confirmCloseCalcDialog: MatDialog
+        private confirmCloseCalcDialog: MatDialog,
+        private _elementRef: ElementRef,
+        private renderer: Renderer2
     ) {
         super();
         this.intlService = ServiceFactory.instance.i18nService;
@@ -308,7 +310,11 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit,
                     // accumulator (valeur précédente du résultat)
                     acc,
                     // currentValue (élément courant dans le tableau)
-                    fieldset
+                    fieldset,
+                    // currentIndex (indice courant dans le tableau)
+                    currIndex,
+                    // array (tableau parcouru)
+                    array
                 ) => {
                     return acc && fieldset.isValid;
                 }
@@ -322,7 +328,11 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit,
                     // accumulator (valeur précédente du résultat)
                     acc,
                     // currentValue (élément courant dans le tableau)
-                    fieldsetContainer
+                    fieldsetContainer,
+                    // currentIndex (indice courant dans le tableau)
+                    currIndex,
+                    // array (tableau parcouru)
+                    array
                 ) => {
                     return acc && fieldsetContainer.isValid;
                 }
@@ -357,6 +367,43 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit,
         this._formulaire.resetResults([]);
     }
 
+    /**
+     * Passe d'un champ de saisie à l'autre lors de l'appui sur
+     * TAB, sans passer par les autres éléments d'interface
+     */
+    public onTabPressed(event: any) {
+        // event source input id
+        const srcId = event.originalEvent.target.id;
+
+        // find all available inputs
+        const qs = "ngparam-input input.form-control";
+        let inputs: Node[] = Array.from(this._elementRef.nativeElement.querySelectorAll(qs));
+
+        // find calculated symbol if any, to exclude it from inputs list
+        let calcSymbol = "";
+        if (this._formulaire.currentNub.calculatedParam) {
+            calcSymbol = this._formulaire.currentNub.calculatedParam.symbol;
+        }
+        inputs = inputs.filter((i: any) => {
+            return i.id !== calcSymbol;
+        });
+
+        // find position among inputs list
+        const currentIndex = inputs.findIndex((i: any) => {
+            return i.id === srcId;
+        });
+
+        // focus previous / next input
+        let newIndex = currentIndex;
+        if (event.shift) {
+            newIndex = (newIndex === 0) ? (inputs.length - 1) : (newIndex - 1);
+        } else {
+            newIndex = (newIndex + 1) % inputs.length;
+        }
+        const elt = (inputs[newIndex] as HTMLElement);
+        elt.focus();
+    }
+
     public openHelp() {
         window.open("assets/docs-fr/calculators/" + this._formulaire.helpLink + "/", "_blank");
     }
diff --git a/src/app/components/generic-input/generic-input.component.html b/src/app/components/generic-input/generic-input.component.html
index f6ca6506f4d99ffcef937546366fca94cbcf63eb..c60194a79e28b460780eace9cbca97dc9caf8311 100644
--- a/src/app/components/generic-input/generic-input.component.html
+++ b/src/app/components/generic-input/generic-input.component.html
@@ -1,6 +1,7 @@
 <mat-form-field>
     <input matInput #inputControl="ngModel" class="form-control" type="text" inputmode="numeric"
         [id]="inputId" [name]="inputId" [disabled]="isDisabled" [(ngModel)]="uiValue" [placeholder]="title"
+        (keydown.Tab)="onTabPressed($event, false)" (keydown.shift.Tab)="onTabPressed($event, true)"
         pattern="^-?([0-9]*\.)?([0-9]+[Ee]-?)?[0-9]+$" required>
 
     <mat-error>{{ errorMessage }}</mat-error>
diff --git a/src/app/components/generic-input/generic-input.component.ts b/src/app/components/generic-input/generic-input.component.ts
index 1bac270188ab49a87be7951a421abad277d45947..0b8b3f09bcd90f653c1cfb983d1146c6f728e019 100644
--- a/src/app/components/generic-input/generic-input.component.ts
+++ b/src/app/components/generic-input/generic-input.component.ts
@@ -59,6 +59,12 @@ export abstract class GenericInputComponent extends BaseComponent implements OnC
     @Output()
     protected change = new EventEmitter<any>();
 
+    /**
+     * événement signalant un appui sur TAB ou SHIFT+TAB
+     */
+    @Output()
+    protected tabPressed = new EventEmitter<any>();
+
     /**
      * valeur saisie.
      * Cette variable n'est modifiée que lorsqu'on affecte le modèle ou que l'utilisateur fait une saisie
@@ -231,6 +237,14 @@ export abstract class GenericInputComponent extends BaseComponent implements OnC
         }
     }
 
+    /**
+     * Renvoie l'événement au composant du dessus
+     */
+    public onTabPressed(event, shift: boolean) {
+        this.tabPressed.emit({ originalEvent: event, shift: shift });
+        return false; // stops event propagation
+    }
+
     private updateAll() {
         this.updateAndValidateUI();
         this.validateModel();
diff --git a/src/app/components/param-field-line/param-field-line.component.html b/src/app/components/param-field-line/param-field-line.component.html
index acea333d21ba24a32813148e8aa38eb7147670f6..1c71eb5b957985b949b08b7862ed29578c6bb4e1 100644
--- a/src/app/components/param-field-line/param-field-line.component.html
+++ b/src/app/components/param-field-line/param-field-line.component.html
@@ -4,7 +4,8 @@
     <!-- input de saisie de la valeur -->
     <div fxFlex="1 0 120px">
         <!-- composant pour gérer le cas général (valeur numérique à saisir) -->
-        <ngparam-input [title]="param.title" [hidden]="! isRadioFixChecked" (change)="onInputChange($event)"></ngparam-input>
+        <ngparam-input [title]="param.title" [hidden]="! isRadioFixChecked"
+            (change)="onInputChange($event)" (tabPressed)="onTabPressed($event)"></ngparam-input>
  
         <!-- composant pour gérer le cas "paramètre calculé" -->
         <param-computed *ngIf="isRadioCalChecked" [title]="title" [param]="param"></param-computed>
diff --git a/src/app/components/param-field-line/param-field-line.component.ts b/src/app/components/param-field-line/param-field-line.component.ts
index 06a78419f964544919d962f0dbe3c70903509b9d..59b38594abab5f9dd8da14bad4eef6d6afb0689e 100644
--- a/src/app/components/param-field-line/param-field-line.component.ts
+++ b/src/app/components/param-field-line/param-field-line.component.ts
@@ -127,6 +127,10 @@ export class ParamFieldLineComponent implements OnChanges {
     @Output()
     private inputChange: EventEmitter<void>;
 
+    /** événement signalant un appui sur TAB ou SHIFT+TAB */
+    @Output()
+    protected tabPressed = new EventEmitter<any>();
+
     /** true si la valeur saisie est valide */
     private _isInputValid = false;
 
@@ -266,6 +270,13 @@ export class ParamFieldLineComponent implements OnChanges {
         this.emitValidity();
     }
 
+    /**
+     * Renvoie l'événement au composant du dessus
+     */
+    public onTabPressed(event) {
+        this.tabPressed.emit(event);
+    }
+
     /**
      * émission d'un événement de validité
      */