Skip to content

Instantly share code, notes, and snippets.

@384400 384400/ -lettre.md
Last active Aug 20, 2016

Embed
What would you like to do?
[Html] [Css] [JavaScript] Comment produire une lettre professionnelle en Html ?

Comment produire une lettre professionnelle en Html ?

Avec quelques rudiments en Html, grâce à un bloc-notes comme [Notepad++] (https://notepad-plus-plus.org/fr/) et à un navigateur, il peut-être intéressant de générer une lettre professionnelle ou commerciale au format A4 à imprimer. À l'heure où les outils bureautiques deviennent complexes et chers, à l'heure où enfle la taille des documents à enregistrer, notre solution se veut frugale et universelle.

Le modus operandi est le suivant (plus long à décrire qu'à exécuter !) :

  • lancement du bloc-notes ;
  • lancement du navigateur ;
  • ouverture du fichier avec le bloc-notes et le navigateur ;
  • rédaction du texte ;
  • impression virtuelle du document (c'est le texte final) au format Pdf ;
  • ouverture et impression réelle du document à travers un lecteur Pdf comme [Adobe Acrobat Reader] (https://get.adobe.com/fr/reader).

Nous avons testé l'impression virtuelle au format Pdf avec les trois principaux navigateurs fonctionnant sous Windows 10 : [Mozilla Firefox] (https://www.mozilla.org/fr/firefox/), [Google Chrome] (https://www.google.com/chrome/), [Microsoft Edge] (https://www.microsoft.com/fr-fr/windows/microsoft-edge). [Google Chrome] (https://www.google.com/chrome/), à travers son moteur [Skia] (https://skia.org/), génère des documents plus légers, qui embarquent nativement chaque police de caractère grâce à l'option Enregistrer au format Pdf. Les trois navigateurs disposent de l'option Microsoft Print to Pdf : le rendu est satisfaisant, les polices de caractère sont fusionnées.

Dans les options d'impression des navigateurs, il faut désactiver les marges ainsi que les en-têtes et les pieds de page éventuels.

À l'origine, nous avions pensé recourir à Xml comme source de texte, mais cette solution, qui nécessite l'usage d'un serveur Web, n'était pas utilisable par tous.

Le [CSS Paged Media Module Level 3] (https://www.w3.org/TR/css3-page/) permettrait peut-être une mise en forme du document sans recourir à JavaScript et à l'impression au format Pdf. Aujourd'hui, cette spécification n'est prise en charge correctement que par [Prince XML] (http://princexml.com/), logiciel qui coûte 495 dollars pour une licence mono-poste (la version gratuite affiche un logotype sur chaque page).

Dans l'exemple que nous présentons, à parfaire (!), nous avons choisi Gentium Basic comme police de caractères. Elle peut être facilement changée.

Nous avons également recouru à la feuille de style proposée par [cognitom] (https://github.com/cognitom/paper-css) : elle permet de voir à l'écran le résultat qui sera imprimé, même si elle souffre de quelques imperfections. Nous avons utilisé la spécification [Flexbox] (https://www.w3.org/TR/css-flexbox-1/), toujours exéprimentale, pour empiler facilement les en-têtes, corps de texte et pieds de page et gérer le placement des blocs de texte. Sans doute serions-nous arrivés à la même présentation en recourant à Grid Layout Module, mais le support est insuffisant.

Nous avons respecté les règles de mise en page d'une lettre commerciale, en suivant les recommandations suivantes...

Est prévue la numérotation des pages, si la lettre en comporte plusieurs, et les points de suite en bas des pages.

Chaque page est séparée par <section></section>. Est affichée par défaut une marge de 20 millimètres en haut, à gauche, à droite, en bas.

Pour la mise en forme, l'auteur doit se soucier du placement correct des paragraphes et créer de nouvelles pages si nécessaire. Notre solution ne permet pas de couper de paragraphes entre chaque page. La première page, c'est-à-dire la première section, doit comprendre la class first-page Les pages suivantes doivent inclure la classe map.

Afin de générer une signature, il suffit d'écrire <p id="signature" class="pull-left pull-top"></p>. Le prénom et le nom de l'auteur s'inscrira à partir des champs renseignés dans la partie expéditeur : <span id="author">Nom Prénom</span>.

Les apostrophes culbutées, les espaces fines ou insécables sont gérées correctement avec JavaScript si var typography = true;. Pour afficher des guillemets, il convient d'utiliser la balise <q><Texte</q>. Attention ! il s'agit de typographie française, car chaque langue dispose de ses propres règles.

L'hyphenation, c'est-à-dire la césure de mots trop longs avec un renvoi à la ligne suivante, n'est correctement pris en charge que par [Mozilla Firefox] (https://www.mozilla.org/fr/firefox/) sous Windows.

Seront à mettre en forme utérieurement...

  • listes ;
  • images ;
  • balise <blockquote></blockquote>.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<title>Lettre</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/3.0.3/normalize.css">
<link rel="stylesheet" href="paper.css">
<!-- https://github.com/cognitom/paper-css -->
<link rel='stylesheet' href="https://fonts.googleapis.com/css?family=Gentium+Basic:400,400i,700,700i&subset=latin-ext">
<style>
/* Attention les marges affichées dans le navigateur ne sont pas précises. En revanche, durant l'exportation au format Pdf, les marges sont parfaitement respectées. */
/* Layout */
@page {
size: A4;
}
@media screen {
header, footer {
background: #efefef;
}
}
.first-page, .map {
display: flex;
flex-direction: column;
}
header {
order: 1;
}
.content {
order: 2;
}
footer {
order: 3;
}
.first-page header {
display: flex;
flex-direction: row;
height: 100mm;
}
.from {
flex-grow: 0;
flex-shrink: 0;
flex-basis: 90mm;
}
.to {
flex-grow: 1;
flex-shrink: 0;
flex-basis: auto;
padding-top: 30mm;
}
.first-page .content {
flex-grow: 1;
flex-shrink: 0;
flex-basis: auto;
}
.first-page footer {
flex-grow: auto;
flex-shrink: 0;
flex-basis: auto;
}
.map header {
font-size: smaller;
}
.map .content {
flex-grow: 1;
flex-shrink: 0;
flex-basis: 0;
}
.pull-left {
padding-left: 90mm;
}
.pull-top {
padding-top: 50mm;
}
header .ornament {
float: left;
}
footer .ornament {
float: right;
}
/* Typography */
body {
font-family: 'Gentium Basic';
font-size: 12pt;
}
strong {
font-family: 'Gentium Basic';
font-weight: 700;
}
em {
font-family: 'Gentium Basic';
font-variant: italic;
}
em strong {
font-family: 'Gentium Basic';
font-style: italic;
font-weight: 700;
}
.content {
hyphens: auto;
line-height: 1.618;
text-align: justify;
}
.to {
font-family: 'Gentium Basic';
font-weight: 700;
}
q {
quotes: "\00AB\A0" "\A0\00BB" "\201C" "\201D" "\2018" "\2019";
}
q:before {
content: open-quote;
}
q:after {
content: close-quote;
}
</style>
</head>
<body class="A4">
<section id="front" class="sheet padding-20mm first-page">
<header>
<div id="sender" class="from">
<span id="author">Nom Prénom</span><br>
Adresse 1<br>
Adresse 2<br>
Code Postal Localité<br>
Pays
</div>
<div id="receiver" class="to">
Nom Prénom<br>
Adresse 1<br>
Adresse 2<br>
Code Postal Localité<br>
Pays
</div>
</header>
<div class="content">
<p id="location-time" class="pull-left">Localité, le <span id="time">1er juillet 2016</span></p>
<p>Appelation,</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras interdum magna tortor, sed elementum nulla auctor et. Phasellus posuere mollis nibh, quis semper lacus auctor quis. Cras id lectus eget dolor aliquet placerat. Mauris varius commodo arcu, sit amet cursus nisl feugiat non. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Quisque ullamcorper varius lacinia. In varius lacus eget metus consectetur efficitur. In a accumsan nibh. Vestibulum feugiat ullamcorper risus nec semper. Nulla at condimentum sem. Ut auctor lorem non mauris interdum imperdiet.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras interdum magna tortor, sed elementum nulla auctor et. Phasellus posuere mollis nibh, quis semper lacus auctor quis. Cras id lectus eget dolor aliquet placerat. Mauris varius commodo arcu, sit amet cursus nisl feugiat non. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Quisque ullamcorper varius lacinia. In varius lacus eget metus consectetur efficitur. In a accumsan nibh. Vestibulum feugiat ullamcorper risus nec semper. Nulla at condimentum sem. Ut auctor lorem non mauris interdum imperdiet.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras interdum magna tortor, sed elementum nulla auctor et. Phasellus posuere mollis nibh, quis semper lacus auctor quis. Cras id lectus eget dolor aliquet placerat. Mauris varius commodo arcu, sit amet cursus nisl feugiat non. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Quisque ullamcorper varius lacinia. In varius lacus eget metus consectetur efficitur. In a accumsan nibh. Vestibulum feugiat ullamcorper risus nec semper. Nulla at condimentum sem. Ut auctor lorem non mauris interdum imperdiet.</p>
</div>
</section>
<section class="sheet padding-20mm map">
<div class="content">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras interdum magna tortor, sed elementum nulla auctor et. Phasellus posuere mollis nibh, quis semper lacus auctor quis. Cras id lectus eget dolor aliquet placerat. Mauris varius commodo arcu, sit amet cursus nisl feugiat non. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Quisque ullamcorper varius lacinia. In varius lacus eget metus consectetur efficitur. In a accumsan nibh. Vestibulum feugiat ullamcorper risus nec semper. Nulla at condimentum sem. Ut auctor lorem non mauris interdum imperdiet.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras interdum magna tortor, sed elementum nulla auctor et. Phasellus posuere mollis nibh, quis semper lacus auctor quis. Cras id lectus eget dolor aliquet placerat. Mauris varius commodo arcu, sit amet cursus nisl feugiat non. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Quisque ullamcorper varius lacinia. In varius lacus eget metus consectetur efficitur. In a accumsan nibh. Vestibulum feugiat ullamcorper risus nec semper. Nulla at condimentum sem. Ut auctor lorem non mauris interdum imperdiet.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras interdum magna tortor, sed elementum nulla auctor et. Phasellus posuere mollis nibh, quis semper lacus auctor quis. Cras id lectus eget dolor aliquet placerat. Mauris varius commodo arcu, sit amet cursus nisl feugiat non. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Quisque ullamcorper varius lacinia. In varius lacus eget metus consectetur efficitur. In a accumsan nibh. Vestibulum feugiat ullamcorper risus nec semper. Nulla at condimentum sem. Ut auctor lorem non mauris interdum imperdiet.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras interdum magna tortor, sed elementum nulla auctor et. Phasellus posuere mollis nibh, quis semper lacus auctor quis. Cras id lectus eget dolor aliquet placerat. Mauris varius commodo arcu, sit amet cursus nisl feugiat non. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Quisque ullamcorper varius lacinia. In varius lacus eget metus consectetur efficitur. In a accumsan nibh. Vestibulum feugiat ullamcorper risus nec semper. Nulla at condimentum sem. Ut auctor lorem non mauris interdum imperdiet.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras interdum magna tortor, sed elementum nulla auctor et. Phasellus posuere mollis nibh, quis semper lacus auctor quis. Cras id lectus eget dolor aliquet placerat. Mauris varius commodo arcu, sit amet cursus nisl feugiat non. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Quisque ullamcorper varius lacinia. In varius lacus eget metus consectetur efficitur. In a accumsan nibh. Vestibulum feugiat ullamcorper risus nec semper. Nulla at condimentum sem. Ut auctor lorem non mauris interdum imperdiet.</p>
</div>
</section>
<section class="sheet padding-20mm map">
<div class="content">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras interdum magna tortor, sed elementum nulla auctor et. Phasellus posuere mollis nibh, quis semper lacus auctor quis. Cras id lectus eget dolor aliquet placerat. Mauris varius commodo arcu, sit amet cursus nisl feugiat non. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Quisque ullamcorper varius lacinia. In varius lacus eget metus consectetur efficitur. In a accumsan nibh. Vestibulum feugiat ullamcorper risus nec semper. Nulla at condimentum sem. Ut auctor lorem non mauris interdum imperdiet.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras interdum magna tortor, sed elementum nulla auctor et. Phasellus posuere mollis nibh, quis semper lacus auctor quis. Cras id lectus eget dolor aliquet placerat. Mauris varius commodo arcu, sit amet cursus nisl feugiat non. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Quisque ullamcorper varius lacinia. In varius lacus eget metus consectetur efficitur. In a accumsan nibh. Vestibulum feugiat ullamcorper risus nec semper. Nulla at condimentum sem. Ut auctor lorem non mauris interdum imperdiet.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras interdum magna tortor, sed elementum nulla auctor et. Phasellus posuere mollis nibh, quis semper lacus auctor quis. Cras id lectus eget dolor aliquet placerat. Mauris varius commodo arcu, sit amet cursus nisl feugiat non. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Quisque ullamcorper varius lacinia. In varius lacus eget metus consectetur efficitur. In a accumsan nibh. Vestibulum feugiat ullamcorper risus nec semper. Nulla at condimentum sem. Ut auctor lorem non mauris interdum imperdiet.</p>
<p id="signature" class="pull-left pull-top"></p>
</div>
</section>
<script>
var typography = true;
var time = document.getElementById('time').textContent;
var author = document.getElementById('author').textContent;
var listPages = document.querySelectorAll('section.map');
for (var i = 0; i < listPages.length; i++) {
var target = i + 2;
var total = listPages.length + 1;
var storeIds = 'map-' + target;
listPages[i].setAttribute('id', storeIds);
var header = document.createElement('header');
header.setAttribute('id', 'header-' + target);
listPages[i].appendChild(header);
var span = document.createElement('span');
span.setAttribute('class', 'ornament');
var ornament = '\u2026\u00A0\u002F\u00A0' + target;
ornament += '\u00A0';
ornament += '\u2013';
ornament += '\u00A0';
ornament += 'De';
ornament += '\u00A0';
ornament += author.toUpperCase();
ornament += '\u00A0';
ornament += '\u2013';
ornament += '\u00A0';
ornament += time;
var contentOrnament = document.createTextNode(ornament);
span.appendChild(contentOrnament);
header.appendChild(span);
if (target < total) {
var footer = document.createElement('footer');
footer.setAttribute('id', 'footer-' + target);
listPages[i].appendChild(footer);
var span = document.createElement('span');
span.setAttribute('class', 'ornament');
var ornament = '\u2026\u00A0\u002F\u00A0\u2026';
var contentOrnament = document.createTextNode(ornament);
span.appendChild(contentOrnament);
footer.appendChild(span);
}
var hasPages = true;
}
if (hasPages) {
var target = 1;
var footer = document.createElement('footer');
footer.setAttribute('id', 'footer-' + target);
document.getElementById('front').appendChild(footer);
var span = document.createElement('span');
span.setAttribute('class', 'ornament');
var ornament = '\u2026\u00A0\u002F\u00A0\u2026';
var contentOrnament = document.createTextNode(ornament);
span.appendChild(contentOrnament);
footer.appendChild(span);
}
if (document.getElementById('signature')) {
var signature = author.toUpperCase();
var contentSignature = document.createTextNode(signature);
document.getElementById('signature').appendChild(contentSignature);
}
if (typography) {
/* Attention aux caractères réservés ! à savoir '. $ ^ { [ ( | ) * + ? \ ' */
document.body.innerHTML = document.body.innerHTML
.replace(/'/g, '\u2019')
.replace(/ : /g, '\u00A0\u003A\u0020')
.replace(/ ; /g, '\u202F\u003B\u0020')
.replace(/ !/g, '\u202F\u0021')
.replace(/ %/g, '\u202F\u0025')
.replace(//g, '\u202F\u2030')
.replace(/ \?/g, '\u202F\u003F')
.replace(/\.\.\./g, '\u2026')
;
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.