Размещение границы внутри div, а не на его краю

506

У меня есть <div>элемент, и я хочу поставить на него границу. Я знаю, что могу писать style="border: 1px solid black", но это добавляет 2px по обе стороны от div, что не то, что я хочу.

Я бы предпочел, чтобы эта граница была -1px от края div. Сам div имеет размер 100px x 100px, и, если я добавлю границу, мне нужно будет немного по математике, чтобы она появилась.

Можно ли как-нибудь сделать так, чтобы граница появилась, и чтобы окно по-прежнему было 100px (включая границу)?

TheMonkeyMan
источник
Для чего это стоит, я опубликовал решение для тех, кто пришел сюда в поисках внутренней границы со смещением
Данилд

Ответы:

662

Установите box-sizingсвойство в 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>

Это работает на IE8 и выше .

Сандип
источник
12
+1. Для немного больше фона: css-tricks.com/box-sizing или paulirish.com/2012/box-sizing-border-box-ftw
изотропной
128
Единственный недостаток этого - вы ДОЛЖНЫ объявить высоту, чтобы он работал, без высоты граница все еще находится за пределами блока и влияет на рендеринг (т. Е. Вертикальный ритм).
Джеркларк
1
это не позволяет стилизовать отдельные граничные стороны, и в этом случае многие, вероятно, будут довольны использованием этого свойства outline.
Лоренц Ло Зауэр
1
Примечание jeremyclarke должно быть в ответе, так как код не работает без установки высоты. примечание: максимальная высота также работает, пока div ИСПОЛЬЗУЕТ это свойство, если высота не достигает максимальной высоты, она не будет работать.
7
Префиксы поставщиков можно удалить для box-sizing caniuse.com/#search=box-sizing
thelostspore
378

Вы также можете использовать box-shadow следующим образом:

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;
}

Пример здесь: http://jsfiddle.net/nVyXS/ (наведите курсор для просмотра границы)

Это работает только в современных браузерах. Например: нет поддержки IE 8. См. Caniuse.com (функция box-shadow) для получения дополнительной информации.

caitriona
источник
30
Любите это решение, потому что оно сохраняет границы полностью внутри коробки, независимо от установленной высоты. Идеально, если вы хотите границы, которые не имеют никакого эффекта вне рамок. Вот CSS для верхней границы 2px: «вставка 0px 2px 0px 0px #DDD»
jerclarke
11
Предпочтительное решение. Кстати, все основные браузеры сегодня поддерживают обычные рамки без тени префикса.
Указатель нулевой
2
Недостатком является то, что некоторые браузеры не могут правильно печатать box-shadow и всегда печатают его как # 000. Это МОЖЕТ стать ограничителем показа, если вам понадобится распечатать страницу.
Роб Фокс
2
Потрясающие! Я думаю, что это лучше, чем первый ответ.
AGamePlayer
1
Перепробовал все остальные .. этот лучше, чем принятый ответ.
Ахсан Аршад
88

Возможно, это запоздалый ответ, но я хочу поделиться своими выводами. Я нашел 2 новых подхода к этой проблеме, которых я не нашел здесь в ответах:

Внутренняя граница через box-shadowсвойство css

Да, box-shadow используется для добавления box-shadows к элементам. Но вы можете указать insetтень, которая будет выглядеть как внутренняя граница, а не как тень. Вам просто нужно установить горизонтальные и вертикальные тени 0pxи spreadсвойство " " box-shadowширины границы, которую вы хотите иметь. Таким образом, для «внутренней» границы 10px вы должны написать следующее:

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

Вот пример jsFiddle, который иллюстрирует разницу между box-shadowграницей и «нормальной» границей. Таким образом, ваша граница и ширина окна составляют 100 пикселей, включая границу.

Подробнее о box-shadow: здесь

Граница через свойство css

Вот другой подход, но таким образом граница будет за пределами коробки. Вот пример . Как следует из примера, вы можете использовать outlineсвойство css , чтобы установить границу, которая не влияет на ширину и высоту элемента. Таким образом, ширина границы не добавляется к ширине элемента.

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

Подробнее о набросках: здесь

Шухрат Раимов
источник
+1 для структуры, это очень эффективный подход, и даже ваша страница w3schools упоминает: «IE8 поддерживает свойство структуры только в том случае, если указан! DOCTYPE».
Armfoot
3
ПРИМЕЧАНИЕ: контур не учитывает радиус границы (проверено в Chrome)
Ник
45

Yahoo! Это действительно возможно. Я нашел это.

Для нижней границы:

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

Для верхней границы:

div {box-shadow: 0px 3px 0px red inset; }
xBoss naYan
источник
28

Используйте псевдоэлемент :

.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>

Используя ::afterвы стилизуете виртуальный последний дочерний элемент выбранного элемента. contentСвойство создает анонимный замененный элемент .

Мы содержат псевдоэлемент, использующий абсолютную позицию относительно родителя. Тогда у вас есть свобода выбора любого собственного фона и / или границы фона основного элемента.

Этот подход не влияет на размещение содержимого основного элемента, который отличается от использования box-sizing: border-box; .

Рассмотрим этот пример:

.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>

Здесь .buttonширина ограничена с использованием родительского элемента. Установка border-left-widthкорректирует размер поля содержимого и, следовательно, положение текста.

.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>

Использование подхода псевдоэлемента не влияет на размер поля содержимого.

В зависимости от приложения подход с использованием псевдоэлемента может быть или не быть желательным поведением.

Gajus
источник
Отлично! Я обнаружил, что это также работает, если вам нужно использовать его :Before.
spasticninja
Отлично! Единственное решение, которое работало для меня на теге привязки, содержащем изображение галереи. Мне нравится тот факт, что он не уменьшает изображение, а визуально обрезает края.
Рышард Йендрашик
21

Хотя этот вопрос уже адекватно ответили решение , используя box-shadowи outlineсвойство, я хотел бы немного расширить это для всех тех , кто высадился здесь (как и я) в поисках решения для внутренней границы с смещением

Допустим, у вас есть черный 100px x 100px, divи вам нужно вставить его в белую рамку - с внутренним смещением 5px (скажем) - это все еще можно сделать с помощью указанных выше свойств.

коробчатого тень

Хитрость заключается в том, чтобы знать, что допускается несколько теней box-box, где первая тень находится сверху, а последующие тени имеют более низкий z-порядок.

С этим знанием объявление box-shadow будет:

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

По сути, это объявление гласит: сначала визуализируем последнюю (10px белую) тень, затем визуализируем предыдущую 5px черную тень над ней.

контур с контуром-смещением

Для того же эффекта, что и выше, наброски объявлений будут:

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

NB: outline-offset не поддерживается IE, если это важно для вас.


Codepen демо

Danield
источник
15

Вы можете использовать свойства outlineи outline-offsetс отрицательным значением вместо обычного border, работает для меня:

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>

Уилсон Дельгадо
источник
Спасибо, этот ответ спас мой день в 2019 году :)
alx
Прекрасный! Это должно быть "один"!
Педро Феррейра
7

Я знаю, что это несколько старше, но так как ключевые слова «граница внутри» привели меня прямо сюда, я хотел бы поделиться некоторыми выводами, которые, возможно, стоит упомянуть здесь. Когда я добавлял границу для состояния наведения, я получил эффекты, о которых говорит OP. Граница рекламирует пиксели в соответствии с размером окна, что делает его нервным. Есть еще два способа справиться с этим, которые также работают для IE7.

1) Иметь границу, уже прикрепленную к элементу, и просто изменить цвет. Таким образом, математика уже включена.

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

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

2) Компенсировать вашу границу с отрицательным запасом. Это все равно добавит лишние пиксели, но позиционирование элемента не будет

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

div:hover {
  margin: -2px;
  border: 2px dashed #333;
}
Даниил
источник
3

для согласованного рендеринга между новыми и старыми браузерами добавьте двойной контейнер, внешний с шириной, внутренний с рамкой.

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

это очевидно, только если ваша точная ширина важнее, чем дополнительная разметка!

выворачивать наизнанку
источник
2

Если вы используете box-sizing: border-box означает не только border, padding, margin и т. Д. Весь элемент будет находиться внутри родительского элемента.

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>

Айяппан К
источник
что, черт возьми, эта цитата
Chud37
0

Лучшее кросс-браузерное решение (в основном для поддержки IE), как сказал @Steve, - это сделать div 98px по ширине и высоте, а затем добавить границу 1px вокруг него, или вы можете создать фоновое изображение для div 100x100 px и нарисовать на нем границу.

mdesdev
источник
0

Вы можете посмотреть на схему со смещением, но для этого нужно добавить некоторые отступы. Или вы можете расположить границу внутри, что-то вроде

<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>

Возможно, вам придется возиться с полями на поддельных границах div, чтобы подогнать его под себя.

Горький
источник
0

Более современным решением может быть использование CSS variablesи calc. calcшироко поддерживается, но variablesеще не в IE11 (полифиллы доступны).

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

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

Хотя для этого используются некоторые расчеты, которых исходные вопросы пытались избежать. Я думаю, что сейчас самое время использовать расчеты, так как они контролируются самим css. Также нет необходимости в дополнительной разметке или незаконном присвоении других свойств CSS, которые могут понадобиться позже.

Это решение действительно полезно, только если фиксированная высота не требуется .

Энди Полхилл
источник
0

Одним из решений, которое я не увидел выше, является случай, когда у вас есть заполнение на входе, что я делаю в 99% случаев. Вы можете сделать что-то вроде ...

input {
  padding: 8px;
}

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

Что мне нравится в этом, так это то, что у меня есть полное меню свойств border + padding + transition для каждой стороны.

Gobot
источник