{"id":185,"date":"2024-08-13T15:09:37","date_gmt":"2024-08-13T15:09:37","guid":{"rendered":"https:\/\/www.accessibilita.digital\/?p=185"},"modified":"2024-08-23T12:27:10","modified_gmt":"2024-08-23T12:27:10","slug":"come-realizzare-un-componente-leggi-di-piu-read-more-accessibile","status":"publish","type":"post","link":"https:\/\/www.accessibilita.digital\/come-realizzare-un-componente-leggi-di-piu-read-more-accessibile\/","title":{"rendered":"Come realizzare un componente Leggi di pi\u00f9 (read more) accessibile"},"content":{"rendered":"<p>Il \u201cread more\u201d \u00e8 un tipo di elemento <b>molto simile all\u2019accordion<\/b> e molto usato nei siti web. Anzi, in buona sostanza potremmo dire che \u00e8 proprio un accordion, e funziona in modo quasi identico.<\/p>\n\n<h2>Read more o accordion?<\/h2>\n<p>La differenza principale in genere sta nel <b>titolo usato per il singolo elemento<\/b>: spesso un accordion generico, come nel caso delle FAQ, riporta il titolo del contenuto che viene a seguire, mentre un elemento \u201cread more\u201d riporta solo la dicitura \u201cLeggi di pi\u00f9\u201d o \u201cScopri\u201d e formule simili. In termini di accessibilit\u00e0 e SEO, <b>non sono dei testi molto adatti<\/b>, ma per le esigenze grafiche e le richieste di cliente finale, si cerca di fare il possibile.<\/p>\n<p>Altra differenza sostanziale \u00e8 che il \u201cread more\u201d ha solitamente <b>una prima porzione di testo gi\u00e0 visibile<\/b>, e una <b>seconda porzione nascosta<\/b> che deve apparire solo quando si aziona il relativo pulsante.<\/p>\n<p>Si crea quindi un caso un po\u2019 particolare che bisogna capire come gestire:<\/p>\n<ul>\n<li>Il primo testo di anteprima spesso <b>contiene i 3 puntini finali<\/b> per far capire che la lettura prosegue oltre<\/li>\n<li><b>Il secondo testo che appare quindi deve essere una continuazione<\/b> del primo, oppure deve <b>nascondere il primo testo e poi contenerlo<\/b> all\u2019interno di s\u00e9 stesso (forse \u00e8 pi\u00f9 semplice capirlo dal codice HTML)<\/li>\n<li>Il pulsante deve avere un testo che faccia capire l\u2019azione all\u2019utente<\/li>\n<\/ul>\n<p>Si tratta quindi di una alternativa piuttosto \u201c<b>custom<\/b>\u201d del classico accordion.<\/p>\n<h2>Esempio pratico con WordPress ed Elementor<\/h2>\n<p>Proviamo a vedere meglio il codice di un esempio che ho realizzato per un <b>sito custom<\/b> fatto con <b>WordPress<\/b> e <b>Bootstrap Italia<\/b>.<\/p>\n<p>In questo caso ho usato <b>Elementor<\/b> sviluppando un <a href=\"https:\/\/developers.elementor.com\/docs\/widgets\/\" rel=\"nofollow noopener\">Widget Custom<\/a> che permettesse al cliente di creare un elemento \u201cRead more\u201d direttamente da editor visuale in backend. La soluzione \u00e8 sicuramente migliorabile, ma a mio avviso rispecchia i requisiti minimi di accessibilit\u00e0, tentando di mantenere comunque una struttura che sia facilmente gestibile da un utente meno esperto.<\/p>\n<p>Rispetto ad altri <b>Visual Builder<\/b> che ho usato, come Divi o WP Bakery, <b>Elementor<\/b> sembra essere quello che permette pi\u00f9 facilmente la <b>personalizzazione<\/b> da parte di noi sviluppatori web, e che allo stesso tempo rispetta in modo pi\u00f9 fedele e \u201cdeveloper-friendly\u201d <b>le linee guida sull\u2019accessibilit\u00e0<\/b>.<\/p>\n<pre class=\"language-markup\"><code>&lt;div class=\"elementor-element elementor-element-d9aab0c e-grid e-con-boxed e-con e-parent e-lazyloaded\" data-id=\"d9aab0c\" data-element_type=\"container\"&gt;\r\n    &lt;div class=\"e-con-inner\"&gt;\r\n        &lt;div class=\"elementor-element elementor-element-fc3befe e-con-full e-flex e-con e-child animated slideInLeft\" data-id=\"fc3befe\" data-element_type=\"container\" data-settings=\"{&amp;quot;animation&amp;quot;:&amp;quot;slideInLeft&amp;quot;}\"&gt;\r\n            &lt;div class=\"elementor-element elementor-element-5ff33aa elementor-widget elementor-widget-image\" data-id=\"5ff33aa\" data-element_type=\"widget\" data-settings=\"{&amp;quot;_animation&amp;quot;:&amp;quot;none&amp;quot;}\" data-widget_type=\"image.default\"&gt;\r\n                &lt;div class=\"elementor-widget-container\"&gt;\r\n                    &lt;img fetchpriority=\"high\" decoding=\"async\" width=\"764\" height=\"700\" src=\"image.jpg\" class=\"attachment-large size-large wp-image-49326\" alt=\"\" srcset=\"image.jpg 764w, image-300x275.jpg 300w, image-273x250.jpg 273w\" sizes=\"(max-width: 764px) 100vw, 764px\"&gt;\r\n                &lt;\/div&gt;\r\n            &lt;\/div&gt;\r\n        &lt;\/div&gt;\r\n        &lt;div class=\"elementor-element elementor-element-bdbe2a7 e-con-full e-flex e-con e-child animated slideInRight\" data-id=\"bdbe2a7\" data-element_type=\"container\" data-settings=\"{&amp;quot;animation&amp;quot;:&amp;quot;slideInRight&amp;quot;}\"&gt;\r\n            &lt;div class=\"elementor-element elementor-element-be66a43 elementor-widget elementor-widget-readmore-custom\" data-id=\"be66a43\" data-element_type=\"widget\" data-settings=\"{&amp;quot;_animation&amp;quot;:&amp;quot;none&amp;quot;}\" data-widget_type=\"readmore-custom.default\"&gt;\r\n                &lt;div class=\"elementor-widget-container\"&gt;\r\n                    &lt;input type=\"checkbox\" id=\"readmore-handler-66b0b89f9e5e2\" class=\"sr-only visually-hidden\" aria-expanded=\"false\" aria-controls=\"readmore-content-wrapper-66b0b89f9e5e2\" tabindex=\"0\" onchange=\"toggleReadMore('#readmore-content-wrapper-66b0b89f9e5e2')\" data-bs-target=\"readmore-content-wrapper-66b0b89f9e5e2\"&gt;\r\n                    &lt;h2&gt;&lt;span class=\"ez-toc-section\" id=\"titolo\" ez-toc-data-id=\"#titolo\"&gt;&lt;\/span&gt;Titolo&lt;span class=\"ez-toc-section-end\"&gt;&lt;\/span&gt;&lt;\/h2&gt;\r\n                    &lt;div id=\"readmore-content-wrapper-66b0b89f9e5e2\" class=\"readmore-content-wrapper\"&gt;\r\n                        &lt;div class=\"readmore-content-preview\"&gt;\r\n                            &lt;p&gt;Lorem ipsum dolor sit amet consectetur adipisicing elit. Repellat enim quasi ut exercitationem veniam cum, dolorem, iusto, in esse velit praesentium illo vel? Aliquid, tempore aspernatur dolor expedita voluptatibus dolorem!&lt;\/p&gt;\r\n                            &lt;p&gt;Lorem ipsum dolor sit amet consectetur adipisicing elit. Repellat enim quasi ut exercitationem veniam cum, dolorem, iusto, in esse velit praesentium illo vel? Aliquid, tempore aspernatur dolor expedita voluptatibus dolorem!&lt;\/p&gt;\r\n                            &lt;p&gt;Questo testo finisce qui...&lt;\/p&gt;\r\n                        &lt;\/div&gt;\r\n                        &lt;div class=\"readmore-content-full\" style=\"display: none;\"&gt;\r\n                            &lt;p&gt;Lorem ipsum dolor sit amet consectetur adipisicing elit. Repellat enim quasi ut exercitationem veniam cum, dolorem, iusto, in esse velit praesentium illo vel? Aliquid, tempore aspernatur dolor expedita voluptatibus dolorem!&lt;\/p&gt;\r\n                            &lt;p&gt;Lorem ipsum dolor sit amet consectetur adipisicing elit. Repellat enim quasi ut exercitationem veniam cum, dolorem, iusto, in esse velit praesentium illo vel? Aliquid, tempore aspernatur dolor expedita voluptatibus dolorem!&lt;\/p&gt;\r\n                            &lt;p&gt;Seconda parte di testo ...&lt;\/p&gt;\r\n                        &lt;\/div&gt;\r\n                    &lt;\/div&gt;\r\n                    &lt;p class=\"handler-label m-0\"&gt;&lt;label for=\"readmore-handler-66b0b89f9e5e2\" tabindex=\"-1\"&gt;Leggi di pi\u00f9&lt;\/label&gt;&lt;\/p&gt;\r\n                &lt;\/div&gt;\r\n            &lt;\/div&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/div&gt;\r\n&lt;script&gt;\r\nfunction toggleReadMore(selector = null)\r\n{\r\n    if (!selector) {\r\n        selector = jQuery(this).attr('data-bs-target');\r\n    }\r\n\r\n    let previewContent = jQuery(selector).find('.readmore-content-preview');\r\n    let fullContent = jQuery(selector).find('.readmore-content-full');\r\n\r\n    jQuery(previewContent).toggle();\r\n    jQuery(fullContent).toggle();\r\n}\r\n&lt;\/script&gt;<\/code><\/pre>\n<p>A parte i vari &lt;div&gt; creati di default da Elementor, questa sezione \u00e8 divisa in <b>due colonne<\/b>, a sinistra abbiamo un\u2019immagine e a destra il testo. Questo testo viene mostrato solo parzialmente e termina con i tre puntini di sospensione, viene poi sostituito dal secondo testo, inizialmente nascosto, che appare solo all\u2019attivazione del pulsante \u201cLeggi di pi\u00f9\u201d.<\/p>\n<h2>Mostrare e nascondere il testo completo<\/h2>\n<p>Vi \u00e8 quindi un piccolo trucchetto, che mira a risolvere il problema di come rendere il secondo testo una continuazione sensata del primo. In pratica, da backend vi sono <b>due campi di testo<\/b>, il primo che contiene <b>il testo di anteprima<\/b>, e il secondo che contiene <b>sia il testo di anteprima sia la sua continuazione<\/b>.<\/p>\n<p>In questo modo, <b>rendiamo pi\u00f9 semplice all\u2019utente che gestisce il sito capire come impostare questo componente personalizzato<\/b>, perch\u00e9 pu\u00f2 inserire il testo completo nel secondo campo, copiarne la prima parte, incollarla nel primo campo di testo e, se lo desidera, inserire in fondo i tre puntini di sospensione.<\/p>\n<p>Il risultato finale \u00e8 che attivando il pulsante, <b>il primo testo viene nascosto<\/b>, e il secondo testo <b>ne prende il posto<\/b>, generalmente riuscendo anche a <b>mantenere la stessa altezza<\/b> di partenza dell\u2019elemento iniziale, che \u00e8 un altro aspetto da non sottovalutare.<\/p>\n<p>Infine, in questo modo \u00e8 pi\u00f9 semplice \u201cspezzare\u201d il testo: l\u2019utente che inserisce i campi in backend <b>non deve pi\u00f9 di tanto preoccuparsi di come dividere<\/b> tra \u201cprima parte\u201d e \u201cseconda parte\u201d, perch\u00e9 come abbiamo detto pu\u00f2 semplicemente <b>copiare e incollare l<\/b><b>e prime righe<\/b> del testo completo.<\/p>\n<p>Nel nostro codice HTML abbiamo molta carne al fuoco, ma proviamo a fare un po\u2019 di ordine e capire quali sono gli <b>elementi principali<\/b> da tenere in considerazione:<\/p>\n<ul>\n<li>Abbiamo un &lt;input type=\u201dcheckbox\u201d&gt; che viene in realt\u00e0 nascosto tramite l\u2019uso delle classi CSS <a href=\"https:\/\/getbootstrap.com\/docs\/4.0\/utilities\/screenreaders\/\" rel=\"nofollow noopener\">sr-only<\/a> (compatibile con Bootstrap 4) e <a href=\"https:\/\/getbootstrap.com\/docs\/5.2\/helpers\/visually-hidden\/\" rel=\"nofollow noopener\">visually-hidden<\/a> (per Bootstrap 5). Inoltre questo checkbox usa <b>aria-expanded<\/b> e <b>aria-controls<\/b> come i button che abbiamo visto in altri esempi, infine \u00e8 collegato ad una <b>funzione Javascript toggleReadMore()<\/b> che <b>mostra o nasconde l\u2019anteprima e il testo completo<\/b>, a seconda che il pulsante sia azionato o meno. Notiamo anche l\u2019uso di tabindex=\u201d-1\u201d sul quale torneremo a breve.<\/li>\n<li>Subito dopo l\u2019input abbiamo un &lt;h2&gt; che contiene <b>il titolo visibile<\/b> del nostro elemento e anche l\u2019\u00e0ncora che viene usata per rimandare l\u2019utente alla sezione specifica di questa pagina<\/li>\n<li>Allo stesso livello dell\u2019input (questo \u00e8 molto importante) abbiamo <b>il contenitore del testo<\/b>, che <b>si divide<\/b> poi tra testo di anteprima (visibile di default) e testo completo (nascosto di default)<\/li>\n<li>Infine, anche questo molto importante, abbiamo un &lt;p&gt; che contiene il <b>&lt;label&gt;<\/b> che viene usato <b>per azionare il checkbox<\/b>: in pratica, usando l\u2019attributo <b>\u201cfor\u201d<\/b> del &lt;label&gt;, <b>popolato con l\u2019id del checkbox<\/b>, riusciamo a collegare i due elementi e renderli interagibili. L\u2019utente clicca l\u2019elemento &lt;label&gt;, il quale agisce sul checkbox. \u00c8 una soluzione simile a quella che abbiamo visto per i <b>men<\/b><b>\u00f9 di navigazione<\/b>. Sul label <b>il tabindex<\/b><b>=\u201d-1\u201d rende l\u2019elemento non raggiungibile<\/b> alle tecnologie assistive e al tabbing della tastiera, mentre il tabindex=\u201d0\u201d sul checkbox lo rende raggiungibile, evitando cos\u00ec una doppia tabulazione quando l\u2019elemento che deve realmente ricevere il focus \u00e8 solo il checkbox.<\/li>\n<\/ul>\n<p>\u00c8 importante che il contenuto e l\u2019elemento &lt;label&gt; siano a pari livello del checkbox, cos\u00ec da renderli raggiungibili in CSS usando il <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/Subsequent-sibling_combinator\" rel=\"nofollow noopener\">selettore sibling<\/a> \u201c~\u201d, ad esempio cos\u00ec:<\/p>\n<pre class=\"language-css\"><code>input[type=\u201dcheckbox\u201d]:checked ~ .handler-label label { opacity:1; }\r\ninput[type=\u201dcheckbox\u201d]:checked ~ .readmore-content-full { display:block; }\r\ninput[type=\u201dcheckbox\u201d]:checked ~ .readmore-content-preview { display:none; }<\/code><\/pre>\n<p>Ovviamente, come gi\u00e0 accennato anche per gli accordion, <b>la soluzione non \u00e8 ideale per i crawler dei motori di ricerca<\/b>, che riusciranno ad indicizzare solo la prima parte visibile del testo (anteprima), tuttavia \u00e8 una buona via di mezzo per incontrare le richieste del cliente.<\/p>\n<h2>Link utili<\/h2>\n<ul>\n<li><a href=\"https:\/\/it.wordpress.org\/plugins\/elementor\/\" rel=\"nofollow noopener\">Elementor WordPress plugin<\/a><\/li>\n<li><a href=\"https:\/\/developers.elementor.com\/docs\/widgets\/\" rel=\"nofollow noopener\">Custom Widgets with Elementor<\/a><\/li>\n<li>Bootstrap 4: <a href=\"https:\/\/getbootstrap.com\/docs\/4.0\/utilities\/screenreaders\/\" rel=\"nofollow noopener\">sr-only<\/a><\/li>\n<li>Boostrap 5.2: <a href=\"https:\/\/getbootstrap.com\/docs\/5.2\/helpers\/visually-hidden\/\" rel=\"nofollow noopener\">visually-hidden<\/a><\/li>\n<li>MDN: <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/Subsequent-sibling_combinator\" rel=\"nofollow noopener\">Subsequent-sibling combinator<\/a><\/li>\n<\/ul>\n<h2>Leggi anche<\/h2>\n<ul>\n<li><a href=\"https:\/\/www.accessibilita.digital\/come-sviluppare-un-sito-web-accessibile\/\">Come sviluppare un sito web accessibile<\/a><\/li>\n<li><a href=\"https:\/\/www.accessibilita.digital\/come-realizzare-una-navigazione-a-briciole-di-pane-breadcrumbs-accessibile\/\">Come realizzare una navigazione a briciole di pane (breadcrumbs) accessibile<\/a><\/li>\n<li><a href=\"https:\/\/www.accessibilita.digital\/come-realizzare-un-menu-di-navigazione-con-dropwn-accessibile\/\">Come realizzare un men\u00f9 di navigazione con dropwn accessibile<\/a><\/li>\n<li><a href=\"https:\/\/www.accessibilita.digital\/come-creare-popup-e-modali-accessibili\/\">Come creare popup e modali accessibili<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Il \u201cread more\u201d \u00e8 un tipo di elemento molto simile all\u2019accordion e molto usato nei siti web. Anzi, in buona sostanza potremmo dire che \u00e8 proprio un accordion, e funziona in modo quasi identico. Read more o accordion? La differenza principale in genere sta nel titolo usato per il singolo elemento: spesso un accordion generico, [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":261,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-185","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/posts\/185"}],"collection":[{"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/comments?post=185"}],"version-history":[{"count":3,"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/posts\/185\/revisions"}],"predecessor-version":[{"id":214,"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/posts\/185\/revisions\/214"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/media\/261"}],"wp:attachment":[{"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/media?parent=185"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/categories?post=185"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/tags?post=185"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}