Creazione di un box-shadow CSS3 su tutti i lati tranne uno


115

Ho una barra di navigazione a schede in cui vorrei che la scheda aperta avesse un'ombra per distinguerla dalle altre schede. Vorrei anche che l'intera sezione delle schede avesse una singola ombra (vedere la linea orizzontale in basso) che saliva, ombreggiando la parte inferiore di tutte le schede tranne quella aperta.

Userò la box-shadowproprietà di CSS3 per farlo, ma non riesco a trovare un modo per ombreggiare solo le parti che voglio.

Normalmente coprirei l'ombra inferiore della scheda aperta con l'area del contenuto (più in alto z-index), ma in questo caso l'area del contenuto stessa ha un'ombra in modo che finisca per coprire la scheda.

Layout a schede

     _______ _______ _______
    | | | | | |
____ | _______ | __ | | __ | _______ | ______

Linea d'ombra.

L'ombra salirà dalle linee orizzontali e verso l'esterno delle linee verticali.

                _______
               | |
_______________ | | _________________

Ecco un esempio dal vivo:

Qualche aiuto là fuori, geni?


23
@the_drow Re: CSS3, mi piace considerare le caratteristiche del design come ombre esterne, angoli arrotondati, ecc. una ricompensa per quegli utenti che utilizzano browser moderni.
bloudermilk

3
WOW, questo è esattamente ciò di cui avevo bisogno, sono contento che esista già una domanda. Anch'io voglio applicare questo a una scheda esattamente come hai mostrato, wow wow wow: D
Jorge Israel Peña

Un altro ottimo modo per risolvere questo problema è usare pseudo elementi, vedi la mia risposta per maggiori dettagli.
Silver Ringvee

Vedi dettagli per pseudo-elemento-soluzione qui: stackoverflow.com/a/38372215/4769218
argento Ringvee

So che questa è una vecchia domanda, ma le dimensioni delle schede sono note? Oppure sono flessibili? Posso immaginare l'altezza potrebbe essere impostata, ma non la larghezza?
Luca

Risposte:


72

Nel tuo esempio, crea un div all'interno di #content con questo stile

#content_over_shadow {
    padding: 1em;
    position: relative; /* look at this */
    background:#fff;    /* a solid background (non transparent) */
}

e cambia lo stile #content (rimuovi i padding) e aggiungi l'ombra

#content {
    font-size: 1.8em;
    box-shadow: 0 0 8px 2px #888; /* line shadow */
}

aggiungi ombre alle schede:

#nav li a {
    margin-left: 20px;
    padding: .7em .5em .5em .5em;
    font-size: 1.3em;
    color: #FFF;
    display: inline-block;
    text-transform: uppercase;
    position: relative;
    box-shadow: 0 0 8px 2px #888; /* the shadow */
}

Manca qualcosa in questa soluzione. Modificando il suo codice e applicando gli stili consigliati, ti ritroverai comunque con un'ombra sulla scheda "selezionata". Sembra che ci sia un overflow: nascosto mancante?
Bob Spryn

1
Sì. Avresti bisogno di un overflow: nascosto nel navigatore per farlo funzionare.
Bob Spryn

1
L '"ombra della linea" mostrata in #content_over_shadowdovrebbe effettivamente essere nello #contentstile di.
AppleGrew

Ebbene questa soluzione mabe era corretta nel 2009, ma ora non lo è. La risposta corretta è stackoverflow.com/a/9800481/835753
Guilherme Ferreira

Una soluzione con elemento pseudo: stackoverflow.com/a/38372215/4769218
argento Ringvee

25

Tagliarlo con troppo pieno.

div div {box-shadow:0 0 5px #000; height:20px}
div {overflow:hidden;height:25px; padding:5px 5px 0 5px}
<div><div>tab</div></div>


3
Ecco anche un esempio con il taglio con overflow starikovs.com/2011/11/09/css3-one-side-shadow .
starikovs

Questo metodo funzionerà solo quando è il lato inferiore su cui non vuoi l'ombra
andrhamm

Funziona alla grande! Il div genitore può essere posizionato sulla correttaz-index
Rvanlaak

Attualmente sto utilizzando questa soluzione, sto riscontrando alcuni problemi con l'elemento figlio che deve essere traboccato (come il pulsante Mi piace di Facebook).
Loenix

1
Non molto utile per i progetti più reattivi in ​​quanto devi impostare l'altezza degli elementi
Jonathan Tonge

13

Puoi utilizzare più ombre CSS senza altri div per ottenere l'effetto desiderato, con l'avvertenza di non avere ombre attorno agli angoli.

div.shadow {
    -webkit-box-shadow: 0 -3px 3px -3px black, 3px 0px 3px -3px black, -3px 0px 3px -3px black;
    -moz-box-shadow:    0 -3px 3px -3px black, 3px 0px 3px -3px black, -3px 0px 3px -3px black;
    box-shadow:         0 -3px 3px -3px black, 3px 0px 3px -3px black, -3px 0px 3px -3px black;
    height: 25px
}
 <div style="height: 25px"><div class="shadow">tab</div></div>

Nel complesso, anche se è molto discreto.


1
Questa sarebbe un'ottima soluzione, ma come dici tu, le curve sono traballanti. jsfiddle.net/mahemoff/ZStTr
mahemoff

1
Ha funzionato come un incantesimo per le mie esigenze di ombra nascosta con angoli arrotondati. Grazie!
Bruno Ely

9

Un altro modo, piuttosto creativo, di risolvere questo problema è aggiungere: after o: before pseudo elemento a uno degli elementi. Nel mio caso sembra così:

#magik_megamenu>li:hover>a:after {
    height: 5px;
    width: 100%;
    background: white;
    content: '';
    position: absolute;
    bottom: -3px;
    left: 0;
}

Guarda lo screenshot, reso rosso lo pseudo elemento per renderlo più visibile.

Guarda lo screenshot, reso rosso lo pseudo elemento per renderlo più visibile.


7

Personalmente mi piace di più la soluzione trovata qui: http://css3pie.com/demos/tabs/

Ti consente di avere uno stato zero o uno stato al passaggio del mouse con un colore di sfondo che ha ancora l'ombra del contenuto sottostante che lo sovrappone. Non sono sicuro che sia possibile con il metodo sopra:

scheda ombreggiata con stato al passaggio del mouse

AGGIORNARE:

In realtà mi sbagliavo. Puoi fare in modo che la soluzione accettata supporti lo stato hover mostrato sopra. Fai questo:

Invece di avere il relativo positivo su a, inseriscilo nella classe a.active con uno z-index che è maggiore del tuo #content div sotto (che ha l'ombra su di esso) ma è inferiore allo z-index sul tuo content_wrapper.

Per esempio:

<nav class="ppMod_Header clearfix">
    <h1 class="ppMod_PrimaryNavigation-Logo"><a class="ppStyle_Image_Logo" href="/">My company name</a></h1>
    <ul class="ppList_PrimaryNavigation ppStyle_NoListStyle clearfix">
        <li><a href="/benefits">Benefits</a></li>
        <li><a class="ppStyle_Active" href="/features">Features</a></li>
        <li><a href="/contact">Contact</a></li>
        <li><a href="/company">Company</a></li>
    </ul>
</nav>
<div id="ppPage-Body">
    <div id="ppPage-BodyWrap">
        content goes here
    </div>
</div>

poi con il tuo css:

#ppPage-Body
    box-shadow: 0 0 12px rgba(0,0,0,.75)
    position: relative /* IMPORTANT PART */

#ppPage-BodyWrap
    background: #F4F4F4
    position: relative /* IMPORTANT PART */
    z-index: 4 /* IMPORTANT PART */


.ppList_PrimaryNavigation li a:hover
    background: #656565
    -webkit-border-radius: 6px 6px 0 0
    -moz-border-radius: 6px 6px 0 0
    border-radius: 6px 6px 0 0

.ppList_PrimaryNavigation li a.ppStyle_Active
    background: #f4f4f4
    color: #222
    -webkit-border-radius: 6px 6px 0 0
    -moz-border-radius: 6px 6px 0 0
    border-radius: 6px 6px 0 0
    -webkit-box-shadow: 0 0 12px rgba(0,0,0,0.75)
    -moz-box-shadow: 0 0 12px rgba(0,0,0,0.75)
    box-shadow: 0 0 12px rgba(0,0,0,0.75)
    position: relative /* IMPORTANT PART */
    z-index: 3 /* IMPORTANT PART */

7

Aggiornare:

clip-path è ora supportato in tutti i principali browser.


Risposta originale:

Se sei disposto a utilizzare la tecnologia sperimentale con un supporto solo parziale , puoi utilizzare la clip-pathproprietà .

Questo produrrà l'effetto desiderato: un'ombra a scatola sui lati superiore, sinistro e destro con un taglio netto sul bordo inferiore.

Nel tuo caso useresti clip-path: inset (px px px px); dove i valori dei pixel sono calcolati dal bordo in questione (vedi sotto).

#container {
    box-shadow: 0 0 8px 2px #888;
    clip-path: inset(-8px -8px 0px -8px);
}

Questo taglierà il div in questione in:

  • 8 pixel sopra la parte superiore (per includere l'ombra)
  • 8 pixel fuori dal bordo destro (per includere l'ombra)
  • 0 pixel dal basso (per nascondere l'ombra)
  • 8 pixel fuori dal bordo sinistro (per includere l'ombra)

Tieni presente che non sono necessarie virgole tra i valori dei pixel.

La dimensione del div può essere flessibile.


Purtroppo c'è uno spazio in cui le due ombre si sovrappongono.
sbaechler

@sbaechler puoi elaborare? Dove si sovrappongono le ombre?
Luca

4

puoi coprire l'ombra usando anche più ombreggiature.

box-shadow: 0 10px 0 #fff, 0 0 10px #ccc;


1

Se hai aggiunto due span a cui agganciarti, potresti usarne due, qualcosa come:

box-shadow: -1px -1px 1px #000;

su una campata e

box-shadow: 1px -1px 1px #000;

su un altro. Potrebbe funzionare!

Se le ombre si sovrappongono potresti persino usare 3 ombre: una 1px a sinistra, una 1px a destra e una 1px in alto, o comunque spesse le desideri.


0

Ho fatto una sorta di hack, non perfetto, ma sembra a posto:

<ul class="tabs">
<li class="tab active"> Tab 1 </li>
<li class="tab"> Tab 2 </li>
<li class="tab"> Tab 3 </li>
</ul>

<div class="tab-content">Content of tab goes here</div>

SCSS

 .tabs { list-style-type: none; display:flex;align-items: flex-end;
  .tab {
    margin: 0;
    padding: 4px 12px;
    border: 1px solid $vivosBorderGrey2;
    background-color:$vivosBorderGrey2;
    color: $vivosWhite;
    border-top-right-radius: 8px;
    border-top-left-radius: 8px;
    border-bottom: 0;
    margin-right: 2px;
    font-size: 14px;
    outline: none;
    cursor: pointer;
    transition: 0.2s;
    &.active {
      padding-bottom: 10px;
      background-color: #ffffff;
      border-color: #eee;
      color: $vivosMedGrey;
      border-bottom-color: transparent;
      box-shadow: 0px -3px 8px -3px rgba(0, 0, 0, 0.1);
    }
    &:hover {padding-bottom: 10px;
    }
   } 

.tabContent {
  border: 1px solid #eee;
  padding:10px;
  margin-top: -1px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.