Soluzione 2020
Ecco una soluzione più moderna che uso in questi giorni.
Inizio generando l'HTML partendo da un array di immagini. Se l'HTML viene generato usando PHP, JS, qualche preprocessore HTML, qualunque cosa ... questo conta meno perché l'idea di base è la stessa.
Ecco il codice Pug che lo farebbe:
//- start with an array of images, described by url and alt text
- let imgs = [
- {
- src: 'image_url.jpg',
- alt: 'image alt text'
- } /* and so on, add more images here */
- ];
- let n_imgs = imgs.length;
- let has_mid = 1; /* 0 if there's no item in the middle, 1 otherwise */
- let m = n_imgs - has_mid; /* how many are ON the circle */
- let tan = Math.tan(Math.PI/m); /* tangent of half the base angle */
.container(style=`--m: ${m}; --tan: ${+tan.toFixed(2)}`)
- for(let i = 0; i < n_imgs; i++)
a(href='#' style=i - has_mid >= 0 ? `--i: ${i}` : null)
img(src=imgs[i].src alt=imgs[i].alt)
L'HTML generato appare come segue (e sì, puoi anche scrivere l'HTML manualmente, ma sarà difficile apportare modifiche in seguito):
<div class="container" style="--m: 8; --tan: 0.41">
<a href='#'>
<img src="image_mid.jpg" alt="alt text"/>
</a>
<a style="--i: 1">
<img src="first_img_on_circle.jpg" alt="alt text"/>
</a>
<!-- the rest of those placed on the circle -->
</div>
Nel CSS, decidiamo una dimensione per le immagini, diciamo 8em. Gli --melementi sono posizionati su un cerchio ed è se sono al centro dei bordi di un poligono di --mbordi, tutti tangenti al cerchio.
Se hai difficoltà a immaginarlo, puoi giocare con questa demo interattiva che costruisce l'incircle e circumcircle per vari poligoni di cui scegli il numero di bordi trascinando il cursore.

Questo ci dice che la dimensione del contenitore deve essere il doppio del raggio del cerchio più due volte la metà delle dimensioni delle immagini.
Non conosciamo ancora il raggio, ma possiamo calcolarlo se conosciamo il numero di bordi (e quindi la tangente della metà dell'angolo di base, precalcolata e impostata come proprietà personalizzata --tan) e il bordo del poligono. Probabilmente vogliamo che il bordo del poligono abbia almeno la dimensione delle immagini, ma quanto lasciamo sui lati è arbitrario. Supponiamo di avere la metà delle dimensioni dell'immagine su ciascun lato, quindi il bordo del poligono è il doppio della dimensione dell'immagine. Questo ci dà il seguente CSS:
.container {
--d: 6.5em; /* image size */
--rel: 1; /* how much extra space we want between images, 1 = one image size */
--r: calc(.5*(1 + var(--rel))*var(--d)/var(--tan)); /* circle radius */
--s: calc(2*var(--r) + var(--d)); /* container size */
position: relative;
width: var(--s); height: var(--s);
background: silver /* to show images perfectly fit in container */
}
.container a {
position: absolute;
top: 50%; left: 50%;
margin: calc(-.5*var(--d));
width: var(--d); height: var(--d);
--az: calc(var(--i)*1turn/var(--m));
transform:
rotate(var(--az))
translate(var(--r))
rotate(calc(-1*var(--az)))
}
img { max-width: 100% }
Vedere la vecchia soluzione per una spiegazione di come funziona la catena di trasformazione.
In questo modo, l'aggiunta o la rimozione di un'immagine dall'array di immagini dispone automaticamente il nuovo numero di immagini su un cerchio in modo che siano equidistanti e regola anche la dimensione del contenitore. Puoi provarlo in questa demo .
VECCHIA soluzione (conservata per ragioni storiche)
Sì, è molto possibile e molto semplice usando solo i CSS. Hai solo bisogno di avere ben in mente gli angoli a cui vuoi i collegamenti con le immagini (ho aggiunto un pezzo di codice alla fine solo per mostrare gli angoli ogni volta che passi il mouse su uno di essi).
Prima hai bisogno di un involucro. Ho impostato il suo diametro su 24em( width: 24em; height: 24em;fa quello), puoi impostarlo su quello che vuoi. Lo dai position: relative;.
Quindi posiziona i tuoi collegamenti con le immagini al centro di quell'involucro, sia orizzontalmente che verticalmente. Puoi farlo impostando position: absolute;e quindi top: 50%; left: 50%;e margin: -2em;(dove 2emè metà della larghezza del collegamento con l'immagine, che ho impostato per essere 4em- di nuovo, puoi cambiarlo come desideri, ma non dimenticare di cambiare il margine in questo caso).
È quindi decidere gli angoli in cui si vogliono avere i tuoi link con le immagini e si aggiunge una classe deg{desired_angle}(ad esempio deg0o deg45o qualsiasi altra cosa). Quindi per ciascuna di queste classi si applicano trasformazioni CSS concatenate, in questo modo:
.deg{desired_angle} {
transform: rotate({desired_angle}) translate(12em) rotate(-{desired_angle});
}
dove si sostituisce {desired_angle}con 0, 45e così via ...
La prima trasformazione di rotazione ruota l'oggetto e i suoi assi, la trasformazione di traslazione trasla l'oggetto lungo l'asse X ruotato e la seconda trasformazione di rotazione riporta l'oggetto in posizione.
Il vantaggio di questo metodo è che è flessibile. È possibile aggiungere nuove immagini da diverse angolazioni senza alterare la struttura corrente.
CODICE SNIPPET
.circle-container {
position: relative;
width: 24em;
height: 24em;
padding: 2.8em;
/*2.8em = 2em*1.4 (2em = half the width of a link with img, 1.4 = sqrt(2))*/
border: dashed 1px;
border-radius: 50%;
margin: 1.75em auto 0;
}
.circle-container a {
display: block;
position: absolute;
top: 50%; left: 50%;
width: 4em; height: 4em;
margin: -2em;
}
.circle-container img { display: block; width: 100%; }
.deg0 { transform: translate(12em); } /* 12em = half the width of the wrapper */
.deg45 { transform: rotate(45deg) translate(12em) rotate(-45deg); }
.deg135 { transform: rotate(135deg) translate(12em) rotate(-135deg); }
.deg180 { transform: translate(-12em); }
.deg225 { transform: rotate(225deg) translate(12em) rotate(-225deg); }
.deg315 { transform: rotate(315deg) translate(12em) rotate(-315deg); }
<div class='circle-container'>
<a href='#' class='center'><img src='image.jpg'></a>
<a href='#' class='deg0'><img src='image.jpg'></a>
<a href='#' class='deg45'><img src='image.jpg'></a>
<a href='#' class='deg135'><img src='image.jpg'></a>
<a href='#' class='deg180'><img src='image.jpg'></a>
<a href='#' class='deg225'><img src='image.jpg'></a>
<a href='#' class='deg315'><img src='image.jpg'></a>
</div>
Inoltre, potresti semplificare ulteriormente l'HTML utilizzando immagini di sfondo per i collegamenti invece di utilizzare i imgtag.
EDIT : esempio con fallback per IE8 e versioni precedenti (testato in IE8 e IE7)