Umieszczanie ramki wewnątrz div, a nie na jej krawędzi

506

Mam <div>element i chcę nałożyć na niego ramkę. Wiem, że umiem pisać style="border: 1px solid black", ale to dodaje 2 piksele po obu stronach div, co nie jest tym, czego chcę.

Wolałbym, aby ta krawędź znajdowała się -1px od krawędzi div. Sama div ma wymiary 100px x 100px, a jeśli dodam ramkę, muszę wykonać matematykę, aby ją wyświetlić.

Czy jest jakiś sposób, aby wyświetlić ramkę i upewnić się, że pole będzie nadal mieć 100 pikseli (w tym ramkę)?

TheMonkeyMan
źródło
Dla tego, co warto, zamieściłem rozwiązanie dla tych, którzy tu przybyli, szukając wewnętrznej granicy z przesunięciem
Danield

Odpowiedzi:

661

Ustaw box-sizingwłaściwość na border-box:

div {
    box-sizing: border-box;
    -moz-box-sizing: border-box;
    -webkit-box-sizing: border-box;
    width: 100px;
    height: 100px;
    border: 20px solid #f00;
    background: #00f;
    margin: 10px;
}

div + div {
    border: 10px solid red;
}
<div>Hello!</div>
<div>Hello!</div>

Działa na IE8 i nowszych .

sandeep
źródło
12
+1. Dla nieco bardziej tle: css-tricks.com/box-sizing lub paulirish.com/2012/box-sizing-border-box-ftw
isotrope
128
Jedyną wadą tego jest to, że MUSISZ zadeklarować wysokość, aby zadziałał, bez wysokości ramka nadal znajduje się poza blokiem i wpływa na rendering (tj. Rytm pionowy).
jerclarke
1
nie pozwala to na stylizowanie pojedynczych granic, aw tym przypadku wielu prawdopodobnie byłoby zadowolonych z korzystania z tej właściwości outline.
Lorenz Lo Sauer,
1
w odpowiedzi powinna znajdować się uwaga jeremyclarke, ponieważ kod nie działa bez ustawienia wysokości. uwaga: maksymalna wysokość również działa, o ile div używa tej właściwości, jeśli wysokość nie osiągnie maksymalnej wysokości, nie będzie działać.
7
Prefiksy dostawców można usunąć dla box-sizing caniuse.com/#search=box-sizing
thelostspore
378

Możesz także użyć cienia pola w następujący sposób:

div{
    -webkit-box-shadow:inset 0px 0px 0px 10px #f00;
    -moz-box-shadow:inset 0px 0px 0px 10px #f00;
    box-shadow:inset 0px 0px 0px 10px #f00;
}

Przykład tutaj: http://jsfiddle.net/nVyXS/ (najedź, aby wyświetlić ramkę)

Działa to tylko w nowoczesnych przeglądarkach. Na przykład: brak obsługi IE 8. Aby uzyskać więcej informacji, zobacz caniuse.com (funkcja box-shadow) .

caitriona
źródło
30
Uwielbiam to rozwiązanie, ponieważ utrzymuje granicę całkowicie wewnątrz pudełka, niezależnie od ustawienia wysokości. Idealne, jeśli chcesz mieć obramowania, które w ogóle nie działają. Oto CSS górnej granicy 2px: „wstawka 0px 2px 0px 0px #DDD”
jerclarke
11
Preferowane rozwiązanie Przy okazji, wszystkie główne przeglądarki obsługują dziś zwykły cień bez prefiksu.
Wskaźnik Null
2
Jednym minusem jest to, że niektóre przeglądarki nie drukują poprawnie box-shadow i zawsze drukują go jako # 000. To MUSI być ogranicznikiem pokazu, jeśli musisz mieć możliwość wydrukowania strony.
Rob Fox
2
Niesamowite! Myślę, że to lepsze niż pierwsza odpowiedź.
AGamePlayer
1
Wypróbowałem wszystkie inne .. ten lepszy niż zaakceptowana odpowiedź.
Ahsan Arshad
88

Prawdopodobnie jest to spóźniona odpowiedź, ale chcę się podzielić z moimi ustaleniami. Znalazłem 2 nowe podejścia do tego problemu, których nie znalazłem tutaj w odpowiedziach:

Wewnętrzna granica za pośrednictwem box-shadowwłaściwości css

Tak, cień-pole służy do dodawania cieni do elementów. Możesz jednak określić insetcień, który wyglądałby jak wewnętrzna ramka, a nie cień. Musisz tylko ustawić cienie poziome i pionowe 0px, a właściwość „ spreadbox-shadowna szerokość ramki, którą chcesz mieć. Tak więc dla „wewnętrznej” granicy 10 pikseli napisałbyś:

div{
    width:100px;
    height:100px;
    background-color:yellow;
    box-shadow:0px 0px 0px 10px black inset;
    margin-bottom:20px;
}

Oto przykład jsFiddle, który ilustruje różnicę między box-shadowramką a „normalną” ramką. W ten sposób twoja ramka i szerokość pudełka wynoszą łącznie 100 pikseli wraz z ramką.

Więcej informacji o box-shadow: tutaj

Obramuj właściwość css konspektu

Oto inne podejście, ale w ten sposób granica byłaby poza ramką. Oto przykład . Jak wynika z tego przykładu, możesz użyć outlinewłaściwości css , aby ustawić granicę, która nie wpływa na szerokość i wysokość elementu. W ten sposób szerokość ramki nie jest dodawana do szerokości elementu.

div{
   width:100px;
   height:100px;
   background-color:yellow;
   outline:10px solid black;
}

Więcej o konspekcie: tutaj

Shukhrat Raimov
źródło
+1 dla konspektu, jest to bardzo skuteczne podejście, a nawet twoja strona w3schools wspomina: «IE8 obsługuje właściwość konspektu tylko wtedy, gdy podano! DOCTYPE.»
Armfoot
3
UWAGA: kontur nie uwzględnia promienia obramowania (testowane w Chrome)
Nick
45

Wieśniak! To jest naprawdę możliwe. Znalazłem to.

Dla dolnej granicy:

div {box-shadow: 0px -3px 0px red inset; }

Dla górnej granicy:

div {box-shadow: 0px 3px 0px red inset; }
xBoss naYan
źródło
28

Użyj pseudoelementu :

.button {
    background: #333;
    color: #fff;
    float: left;
    padding: 20px;
    margin: 20px;
    position: relative;
}

.button::after {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    border: 5px solid #f00;
}
<div class='button'>Hello</div>

Za pomocą ::afterprojektujesz wirtualne ostatnie dziecko wybranego elementu. contentwłaściwość tworzy anonimowy zastąpiony element .

Zawieramy pseudoelement przy użyciu pozycji bezwzględnej względem rodzica. Masz wtedy swobodę posiadania dowolnego niestandardowego tła i / lub obramowania w tle głównego elementu.

To podejście nie wpływa na umieszczenie zawartości głównego elementu, co różni się od używania box-sizing: border-box;.

Rozważ ten przykład:

.parent {
    width: 200px;
}

.button {
    background: #333;
    color: #fff;
    padding: 20px;
    border: 5px solid #f00;
    border-left-width: 20px;
    box-sizing: border-box;
}
<div class='parent'>
    <div class='button'>Hello</div>
</div>

Tutaj .buttonszerokość jest ograniczona za pomocą elementu nadrzędnego. Ustawienie border-left-widthdopasowań dostosowuje rozmiar pola zawartości, a tym samym pozycję tekstu.

.parent {
    width: 200px;
}

.button {
    background: #333;
    color: #fff;
    padding: 20px;
    position: relative;
}

.button::after {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    border: 5px solid #f00;
    border-left-width: 20px;
}
<div class='parent'>
    <div class='button'>Hello</div>
</div>

Zastosowanie podejścia pseudoelementowego nie wpływa na rozmiar pola zawartości.

W zależności od aplikacji podejście przy użyciu pseudoelementu może, ale nie musi być pożądanym zachowaniem.

Gajus
źródło
Doskonały! Okazało się, że działa to również, jeśli musisz go użyć :Before.
spasticninja
Wybitny! Jedyne rozwiązanie, które działało dla mnie na tagu kotwicy zawierającym obraz galerii. Podoba mi się to, że nie przeskalowuje obrazu, ale zamiast tego wizualnie przycina krawędzie.
Ryszard Jędraszyk
21

Chociaż na to pytanie została już odpowiednio udzielona odpowiedź za pomocą rozwiązań wykorzystujących box-shadowi outline, chciałbym nieco rozwinąć tę kwestię dla wszystkich tych, którzy wylądowali tutaj (jak ja) szukając rozwiązania dla wewnętrznej granicy z przesunięciem

Powiedzmy, że masz czarną 100px x 100px divi musisz wstawić ją białą ramką - która ma wewnętrzne przesunięcie 5px (powiedzmy) - nadal można to zrobić z powyższymi właściwościami.

cień-pudełko

Sztuczka polega na tym, aby wiedzieć, że dozwolonych jest wiele cieni w ramkach, gdzie pierwszy cień jest na górze, a kolejne cienie mają niższą kolejność.

Przy tej wiedzy deklaracja w tle będzie następująca:

box-shadow: inset 0 0 0 5px black, inset 0 0 0 10px white;

Zasadniczo, deklaracja ta mówi: renderuj pierwszy (10 pikseli biały) cień, a następnie renderuj poprzedni czarny cień 5 pikseli powyżej.

kontur z przesunięciem konturu

Dla takiego samego efektu jak powyżej deklaracje konspektu byłyby następujące:

outline: 5px solid white;
outline-offset: -10px;

Uwaga: outline-offset nie jest obsługiwany przez IE, jeśli jest to dla Ciebie ważne.


Demo Codepen

Danield
źródło
15

Możesz użyć właściwości outlinei outline-offsetz wartością ujemną zamiast zwykłego border, działa dla mnie:

div{
    height: 100px;
    width: 100px;
    background-color: grey;
    margin-bottom: 10px; 
}

div#border{
    border: 2px solid red;
}

div#outline{
    outline: 2px solid red;
    outline-offset: -2px;
}
Using a regular border.
<div id="border"></div>

Using outline and outline-offset.
<div id="outline"></div>

Wilson Delgado
źródło
Dziękuję, ta odpowiedź uratowała mi dzień w 2019 roku :)
alx
Piękny! To powinien być „ten jedyny”!
Pedro Ferreira
7

Wiem, że jest to nieco starsze, ale ponieważ słowa kluczowe „granica w środku” znalazły mnie tutaj bezpośrednio, chciałbym podzielić się niektórymi spostrzeżeniami, o których warto tu wspomnieć. Kiedy dodawałem granicę w stanie unoszenia, dostałem efekty, o których mówi OP. Obramowanie reklamuje piksele do wymiarów pudełka, co spowodowało, że jest on zwichnięty. Istnieją dwa inne sposoby radzenia sobie z tym, które działają również w IE7.

1) Miej już przymocowaną ramkę do elementu i po prostu zmień kolor. W ten sposób matematyka jest już uwzględniona.

div {
   width:100px;
   height:100px;
   background-color: #aaa;
   border: 2px solid #aaa; /* notice the solid */
}

div:hover {
   border: 2px dashed #666;
}

2) Zrekompensuj swoją granicę ujemnym marginesem. Nadal doda to dodatkowe piksele, ale pozycjonowanie elementu nie będzie przeskakujące

div {
   width:100px;
   height:100px;
   background-color: #aaa;
}

div:hover {
  margin: -2px;
  border: 2px dashed #333;
}
Daniel
źródło
3

w celu spójnego renderowania między nowymi i starszymi przeglądarkami dodaj podwójny pojemnik, zewnętrzny o szerokości, wewnętrzny z ramką.

<div style="width:100px;">
<div style="border:2px solid #000;">
contents here
</div>
</div>

jest to oczywiście tylko wtedy, gdy dokładna szerokość jest ważniejsza niż dodatkowe znaczniki!

Wynicować
źródło
2

Jeśli używasz zmiany rozmiaru ramki: ramka oznacza nie tylko ramkę, wypełnienie, margines itp. Wszystkie elementy wejdą do elementu nadrzędnego.

div p {
    box-sizing: border-box;
    -moz-box-sizing: border-box;
    -webkit-box-sizing: border-box;
    width: 150px;
    height:100%;
    border: 20px solid #f00;
    background-color: #00f;
    color:#fff;
    padding: 10px;
  
}
<div>
  <p>It was popularised in the 1960s with the release of Letraset sheets</p>
</div>

Ayyappan K.
źródło
co to do cholery jest ten cytat
Chud37,
0

Najlepszym rozwiązaniem dla różnych przeglądarek (głównie do obsługi IE), jak powiedział @Steve, jest zrobienie div 98px szerokości i wysokości niż dodanie obramowania 1px wokół niego, lub możesz zrobić obraz tła dla div 100x100 px i narysować na nim ramkę.

mdesdev
źródło
0

Możesz spojrzeć na kontur z przesunięciem, ale wymaga to dopełnienia, aby istniało na div. Możesz też absolutnie umieścić wewnątrz div div, coś w stylu

<div id='parentDiv' style='position:relative'>
  <div id='parentDivsContent'></div>
  <div id='fakeBordersDiv' 
       style='position: absolute;width: 100%;
              height: 100%;
              z-index: 2;
              border: 2px solid;
              border-radius: 2px;'/>
</div>

Być może będziesz musiał manipulować marginesami na fałszywym div div, aby dopasować go tak, jak chcesz.

Gorki
źródło
0

Bardziej nowoczesnym rozwiązaniem może być użycie css variablesi calc. calcjest szeroko obsługiwany, ale variablesnie jest jeszcze dostępny w IE11 (dostępne polypełniacze).

:root {
  box-width: 100px;
  border-width: 1px;
}

#box {
  width: calc(var(--box-width) - var(--border-width));
}

Chociaż wykorzystuje to pewne obliczenia, których pierwotne pytania starano się uniknąć. Myślę, że to dobry czas na użycie obliczeń, ponieważ są one kontrolowane przez sam css. Nie ma też potrzeby dodawania znaczników ani przywłaszczania innych właściwości css, które mogą być później potrzebne.

To rozwiązanie jest naprawdę przydatne tylko wtedy, gdy nie jest wymagana stała wysokość .

Andy Polhill
źródło
0

Jednym z rozwiązań, których nie widziałem powyżej, jest przypadek, w którym wypełniasz dane wejściowe, co robię w 99% przypadków. Możesz zrobić coś w stylu ...

input {
  padding: 8px;
}

input.invalid {
  border: 2px solid red;
  padding: 6px; // 8px - border or "calc(8px - 2px)"
}

Podoba mi się to, że mam pełne menu właściwości border + padding + przejścia dla każdej strony.

Gobot
źródło