рисовать диагональные линии на фоне div с помощью CSS

У меня есть div для окна предварительного просмотра:

HTML:

<div class="preview-content">PREVIEW</div>

CSS:

.preview-content {
    background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAGklEQVQIW2NkYGD4D8SMQAwGcAY2AbBKDBUAVuYCBQPd34sAAAAASUVORK5CYII=) repeat;
    width: 100%;
    min-height: 300px;
    max-height: 300px;
    line-height: 300px;
    text-align: center;
    vertical-align: middle;
     font-size: 2em;
}

Вопрос: как добавить диагональные линии на фон div как на картинке?

примечание: только с CSS, если это возможно

предварительный просмотр

Заранее спасибо.


person Ing. Michal Hudak    schedule 02.08.2013    source источник
comment
Вы просто хотите добавить две строки?   -  person cdMinix    schedule 02.08.2013
comment
да, только 2 как на картинке   -  person Ing. Michal Hudak    schedule 02.08.2013


Ответы (12)


Вы можете сделать это примерно так:

<style>
    .background {
        background-color: #BCBCBC;
        width: 100px;
        height: 50px;
        padding: 0; 
        margin: 0
    }
    .line1 {
        width: 112px;
        height: 47px;
        border-bottom: 1px solid red;
        -webkit-transform:
            translateY(-20px)
            translateX(5px)
            rotate(27deg); 
        position: absolute;
        /* top: -20px; */
    }
    .line2 {
        width: 112px;
        height: 47px;
        border-bottom: 1px solid green;
        -webkit-transform:
            translateY(20px)
            translateX(5px)
            rotate(-26deg);
        position: absolute;
        top: -33px;
        left: -13px;
    }
</style>
<div class="background">
    <div class="line1"></div>
    <div class="line2"></div>
</div>

Вот jsfiddle.

Улучшенная версия ответа для ваших целей.

person AxelPAL    schedule 02.08.2013
comment
С -webkit-transform будет работать только в браузерах на основе WebKit. Я предлагаю указать стандартное правило W3C transform в качестве первого шага, а затем указать другое правило для конкретного браузера, например -webkit-transform, -moz-transform, -ms-transform, -o-transform. - person T-moty; 03.11.2014

Почти идеальным решением, которое автоматически масштабируется до размеров элемента, было бы использование линейного градиента CSS3, связанного с calc(), как показано ниже. Главный недостаток — это, конечно, совместимость. Код ниже работает в Firefox 25 и Explorer 10 и 11, но в Chrome (я тестировал v30 и v32 dev) есть некоторые тонкие проблемы с исчезновением линий, если они слишком узкие. Кроме того, исчезновение зависит от размеров окна — стиль ниже работает для div { width: 100px; height: 100px}, но не работает для div { width: 200px; height: 200px}, для которого в моих тестах 0.8px в расчетах нужно заменить как минимум на 1.1048507095px для отображения диагоналей, и даже тогда качество рендеринга линий довольно низкое. Будем надеяться, что эта ошибка Chrome скоро будет решена.

.crossed {
     background: 
         linear-gradient(to top left,
             rgba(0,0,0,0) 0%,
             rgba(0,0,0,0) calc(50% - 0.8px),
             rgba(0,0,0,1) 50%,
             rgba(0,0,0,0) calc(50% + 0.8px),
             rgba(0,0,0,0) 100%),
         linear-gradient(to top right,
             rgba(0,0,0,0) 0%,
             rgba(0,0,0,0) calc(50% - 0.8px),
             rgba(0,0,0,1) 50%,
             rgba(0,0,0,0) calc(50% + 0.8px),
             rgba(0,0,0,0) 100%);
}
<textarea class="crossed"></textarea>

person RobertT    schedule 07.11.2013
comment
Вот jsfiddle на случай, если вы захотите поиграть с этим решением: jsfiddle.net/zaxy6pmn - person danvk; 30.11.2014
comment
Выглядит в основном нормально в Chrome 39, но в правом нижнем углу есть лишний пиксель. В зависимости от того, что находится вокруг, это может быть незаметно, за исключением очень маленьких размеров, например. 5х5 пикселей. - person mrec; 19.01.2015
comment
Хорошее решение. Обновлен для фонового повторения: jsfiddle.net/6q4m4ww8 Теперь моя проблема заключается в том, как добавить расстояние между x- эс - person Daniel Ursu; 16.05.2017
comment
Вы имеете в виду что-то вроде http://jsfiddle.net/8f5rgn8t/? ;) (хотя, вероятно, потребуется немного больше настройки для более толстых линий, так как каждая линия имеет один конец, обрезанный по вертикальной стороне ограничивающей рамки, а второй - по горизонтали) - person RobertT; 16.05.2017
comment
Что если я захочу изменить цвет фона на серый вместо белого? - person Bargain23; 08.09.2019
comment
@Bargain23 Измените значения rgba на значения серого. - person TylerH; 26.09.2019
comment
Лучший :) Как по мне - person Tsurule Vol; 10.02.2021
comment
Идеальное многоразовое решение - person jis0324; 29.06.2021

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

.diag {
    background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' version='1.1' preserveAspectRatio='none' viewBox='0 0 100 100'><path d='M1 0 L0 1 L99 100 L100 99' fill='black' /><path d='M0 99 L99 0 L100 1 L1 100' fill='black' /></svg>");
    background-repeat:no-repeat;
    background-position:center center;
    background-size: 100% 100%, auto;
}
<div class="diag" style="width: 300px; height: 100px;"></div>

Поиграйте здесь: http://jsfiddle.net/tyw7vkvm

person intrepidis    schedule 10.03.2015
comment
Хороший! Искал решение для имитации перечеркнутой цены, и это отлично сработало с несколькими незначительными изменениями jsfiddle.net/tyw7vkvm /636 ???? - person Mavelo; 26.08.2018
comment
@intrepidis Как увеличить толщину линий? - person Tony Mathew; 21.01.2020
comment
Это что-то вроде <path stroke-width='2' d='...'> - person intrepidis; 21.01.2020
comment
@TonyMathew здесь имеет толщину 4 пикселя: <path d='M 4 0 L 4 0 L 0 0 L 0 4 L 96 100 L 100 100 L 100 96' fill='black' /><path d='M 96 0 L 96 0 L 100 0 L 100 4 L 4 100 L 0 100 L 0 96' fill='black' /> просто измените 4 и 96 на любую нужную вам толщину. (например, 2 и 98, 5 и 95) - person Sam Eaton; 22.05.2020

Все остальные ответы на этот трехлетний вопрос требуют CSS3 (или SVG). Однако это также можно сделать с помощью старого хромого CSS2:

.crossed {
    position: relative;
    width: 300px;
    height: 300px;
}

.crossed:before {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: 1px;
    bottom: 1px;
    border-width: 149px;
    border-style: solid;
    border-color: black white;
}

.crossed:after {
    content: '';
    position: absolute;
    left: 1px;
    right: 1px;
    top: 0;
    bottom: 0;
    border-width: 149px;
    border-style: solid;
    border-color: white transparent;
}
<div class='crossed'></div>

Пояснение, как и просили:

Вместо того, чтобы рисовать диагональные линии, мне пришло в голову, что мы можем вместо этого раскрасить так называемые треугольники отрицательного пространства рядом с тем местом, где мы хотим видеть эти линии. Уловка, которую я придумал, чтобы добиться этого, использует тот факт, что разноцветные рамки CSS скошены по диагонали:

.borders {
    width: 200px;
    height: 100px;
    background-color: black;
    border-width: 40px;
    border-style: solid;
    border-color: red blue green yellow;
}
<div class='borders'></div>

Чтобы все подошло так, как мы хотим, мы выбираем внутренний прямоугольник с размерами 0 и LINE_THICKNESS пикселей, а другой — с обратными размерами:

.r1 { width: 10px;
      height: 0;
      border-width: 40px;
      border-style: solid;
      border-color: red blue;
      margin-bottom: 10px; }
.r2 { width: 0;
      height: 10px;
      border-width: 40px;
      border-style: solid;
      border-color: blue transparent; }
<div class='r1'></div><div class='r2'></div>

Наконец, используйте псевдоселекторы :before и :after и позиционируйте относительное/абсолютное как аккуратный способ вставить границы обоих вышеупомянутых прямоугольников друг над другом в выбранный вами элемент HTML, чтобы создать диагональный крест. Обратите внимание, что результаты, вероятно, выглядят лучше всего при тонком значении LINE_THICKNESS, таком как 1 пиксель.

person Will    schedule 16.07.2016
comment
Да, хороший трюк, но игнорирует одно предположение исходного вопроса: width: 100% из div нужно пересечь;) Хотя, честно говоря, предположение из принятого ответа, похоже, не было сложным требованием. - person RobertT; 16.05.2017

Пожалуйста, проверьте следующее.

<canvas id="myCanvas" width="200" height="100"></canvas>
<div id="mydiv"></div>

JS:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.strokeStyle="red";
ctx.moveTo(0,100);
ctx.lineTo(200,0);
ctx.stroke();
ctx.moveTo(0,0);
ctx.lineTo(200,100);
ctx.stroke();

CSS:

html, body { 
  margin: 0;
  padding: 0;
}

#myCanvas {
  padding: 0;
  margin: 0;
  width: 200px;
  height: 100px;
}

#mydiv {
  position: absolute;
  left: 0px;
  right: 0;
  height: 102px;
  width: 202px;
  background: rgba(255,255,255,0);
  padding: 0;
  margin: 0;
}

jsfiddle

person Saritha.S.R    schedule 02.08.2013
comment
обратите внимание, что ширина равна 100%, width: 100%; поэтому поле будет плавающим, поэтому я не могу записать постоянные координаты в js - person Ing. Michal Hudak; 02.08.2013

intrepidis' answer на этой странице с использованием фонового SVG в CSS имеет то преимущество, что оно хорошо масштабируется до любого размера или соотношения сторон, хотя SVG использует <path>s с заливкой, которая не так хорошо масштабируется.

Я только что обновил код SVG, чтобы использовать <line> вместо <path>, и добавил non-scaling-stroke vector-effect, чтобы предотвратить масштабирование штрихов с помощью контейнер:

<svg xmlns='http://www.w3.org/2000/svg' version='1.1' preserveAspectRatio='none' viewBox='0 0 100 100'>
  <line x1='0' y1='0' x2='100' y2='100' stroke='black' vector-effect='non-scaling-stroke'/>
  <line x1='0' y1='100' x2='100' y2='0' stroke='black' vector-effect='non-scaling-stroke'/>
</svg>

Вот что попало в CSS из исходного ответа (с изменяемым размером HTML):

.diag {
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' version='1.1' preserveAspectRatio='none' viewBox='0 0 100 100'><line x1='0' y1='0' x2='100' y2='100' stroke='black' vector-effect='non-scaling-stroke'/><line x1='0' y1='100' x2='100' y2='0' stroke='black' vector-effect='non-scaling-stroke'/></svg>");
  background-repeat: no-repeat;
  background-position: center center;
  background-size: 100% 100%, auto;
}
<div class="diag" style="width: 200px; height: 150px; border: 1px solid; resize: both; overflow: auto"></div>

person Shaw    schedule 12.06.2019

вы можете использовать свойство преобразования CSS3:

div
{
transform:rotate(Xdeg);
-ms-transform:rotate(Xdeg); /* IE 9 */
-webkit-transform:rotate(Xdeg); /* Safari and Chrome */
}

Xdeg = ваше значение

Например...

Вы можете сделать больше div и использовать свойство z-index. Итак, сделайте div с линией и поверните его.

person Reverter    schedule 02.08.2013

Если вы хотите, чтобы крест был частично прозрачным, наивным подходом было бы сделать linear-gradient цветов полупрозрачными. Но это не работает из-за альфа-смешения на пересечении, в результате чего получается алмаз другого цвета. Решение этой проблемы состоит в том, чтобы оставить цвета сплошными, но вместо этого добавить прозрачность в контейнер градиента:

.cross {
  position: relative;
}
.cross::after {
  pointer-events: none;
  content: "";
  position: absolute;
  top: 0; bottom: 0; left: 0; right: 0;
}

.cross1::after {
  background:
    linear-gradient(to top left, transparent 45%, rgba(255,0,0,0.35) 46%, rgba(255,0,0,0.35) 54%, transparent 55%),
    linear-gradient(to top right, transparent 45%, rgba(255,0,0,0.35) 46%, rgba(255,0,0,0.35) 54%, transparent 55%);
}

.cross2::after {
  background:
    linear-gradient(to top left, transparent 45%, rgb(255,0,0) 46%, rgb(255,0,0) 54%, transparent 55%),
    linear-gradient(to top right, transparent 45%, rgb(255,0,0) 46%, rgb(255,0,0) 54%, transparent 55%);
  opacity: 0.35;
}

div { width: 180px; text-align: justify; display: inline-block; margin: 20px; }
<div class="cross cross1">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam et dui imperdiet, dapibus augue quis, molestie libero. Cras nisi leo, sollicitudin nec eros vel, finibus laoreet nulla. Ut sit amet leo dui. Praesent rutrum rhoncus mauris ac ornare. Donec in accumsan turpis, pharetra eleifend lorem. Ut vitae aliquet mi, id cursus purus.</div>

<div class="cross cross2">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam et dui imperdiet, dapibus augue quis, molestie libero. Cras nisi leo, sollicitudin nec eros vel, finibus laoreet nulla. Ut sit amet leo dui. Praesent rutrum rhoncus mauris ac ornare. Donec in accumsan turpis, pharetra eleifend lorem. Ut vitae aliquet mi, id cursus purus.</div>

person user    schedule 29.04.2019

Вот как я сделал это, используя свойство css clip-path вместе с относительным и абсолютным позиционированием, чтобы создать более причудливый крест.

.cross {
  width:150px;
  height: 150px;
  border: 2px solid #555;
  border-radius: 5px;
  position: relative;
  background: #efefef;
}

.cross .diag1{
  position: absolute;
  width:100%; height:100%;
  clip-path: polygon(90% 0, 100% 0%, 10% 100%, 0% 100%);
  background: #311B92;
}

.cross .diag2{
  position: absolute;
  width:100%; height:100%;
  clip-path: polygon(0 0, 10% 0, 100% 100%, 90% 100%);
  background: #1B5E20;
}
<div class="cross">
  <div class="diag1"></div>
  <div class="diag2"></div>
</div>

Вот ссылка на код на codepen, если вы хотите его изменить.

person Cels    schedule 01.03.2020

Динамическое решение SVG для любого экрана выглядит следующим образом:

<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" stroke-width="1" stroke="#000">
  <line x1="0" y1="0" x2="100%" y2="100%"/>
  <line x1="100%" y1="0" x2="0" y2="100%"/>
</svg>

И если вы хотите сохранить его в фоновом режиме, используйте position: absolute с верхним и левым 0.

person Romanos    schedule 25.11.2020

введите здесь описание изображения

.crossed {
    width: 200px;
    height: 200px;
    border:solid 1px;
    background-color: rgb(210, 137, 226);
    background-image: repeating-linear-gradient(
      45deg,
      transparent,
      transparent 15px,
      #ccc 10px,
      #ccc 20px
        ),
      repeating-linear-gradient(
        135deg,
        transparent,
        transparent 15px,
        #ccc 10px,
        #ccc 20px
      );
}
<div class='crossed'>Hello world</div>

person Prahlad    schedule 01.10.2020
comment
Спасибо! Я просто смотрел это. - person Adrian Kalinowski; 03.03.2021

Мне нужно было нарисовать произвольные диагональные линии внутри любого div. Моя проблема с другими опубликованными ответами заключается в том, что ни один из них не позволял провести произвольную линию из точки A в точку B, не выполняя самостоятельно тригонометрию для углов. С помощью javascript и CSS вы можете это сделать. Надеюсь, это полезно, просто укажите пару баллов, и вы золотой.

const objToStyleString = (obj) => {
  const reducer = (acc, curr) => acc += curr + ": " + obj[curr] + ";"; 
  return Object.keys(obj).reduce(reducer, "")
};

const lineStyle = (xy1, xy2, borderStyle) => {
  const p1 = {x: xy1[0], y: xy1[1]};
  const p2 = {x: xy2[0], y: xy2[1]};
  
  const a = p2.x - p1.x;
  const xOffset = p1.x;
  const b = p2.y - p1.y;
  const yOffset = p1.y;
  
  const c = Math.sqrt(a*a + b*b);
  
  const ang = Math.acos(a/c);
  
  const tX1 = `translateX(${-c/2 + xOffset}px) `;
  const tY1 = `translateY(${yOffset}px) `;
  const rot = `rotate(${ang}rad) `;
  const tX2 = `translateX(${c/2}px) `;
  const tY2 = `translateY(${0}px) `;
  
  return {
    "width": Math.floor(c) + "px",
    "height": "0px",
    "border-top": borderStyle,
    "-webkit-transform": tX1+tY1+rot+tX2+tY2,
    "position": "relative",
    "top": "0px",
    "left": "0px",
    "box-sizing": "border-box",
  };
};

function drawLine(parent, p1, p2, borderStyle) {
  const style = lineStyle(p1, p2, borderStyle);
  const line = document.createElement("div");
  line.style = objToStyleString(style);
  parent.appendChild(line);
}

drawLine(container, [100,5], [25,195], "1px dashed purple");
drawLine(container, [100,100], [190,190], "1px solid blue");
drawLine(container, [25,150], [175,150], "2px solid red");
drawLine(container, [25,10], [175,20], "5px dotted green");
#container {
  background-color: #BCBCBC;
  width: 200px;
  height: 200px;
  padding: 0; 
  margin: 0;
}
<div id="container">
</div>

person skb    schedule 18.01.2020