Как делает CSS 'overflow:hidden', работают, чтобы вынудить элемент (содержащий пущенные в ход элементы) перенести пущенные в ход элементы?

Этот вопрос составляет около 2-х лет, но я придумал (что я думаю) изящное решение, и подумал, что поделюсь им с хорошими людьми здесь, в StackOverflow. Надеюсь, это поможет тем, кто приезжает сюда через различные поисковые запросы.

Проблема, как заявил плакат, заключается в том, чтобы получить правильный общий метод. Например, метод расширения LINQ может иметь массу перегрузок с аргументами типа, вложенными в другие общие типы, которые все используются как параметры. Я хотел сделать что-то вроде этого:

var where = typeof(Enumerable).GetMethod(
  "Where", 
  typeof(IQueryable<Refl.T1>), 
  typeof(Expression<Func<Refl.T1, bool>>
);

var group = typeof(Enumerable).GetMethod(
  "GroupBy", 
  typeof(IQueryable<Refl.T1>), 
  typeof(Expression<Func<Refl.T1, Refl.T2>>
);

Как вы можете видеть, я создал несколько типов заглушек «T1» и «T2», вложенные классы в классе «Refl» (статический класс который содержит все мои различные функции расширения утилиты Reflection и т. д. Они служат в качестве заполнителей для тех параметров, которые обычно выполнялись бы. Приведенные выше примеры соответствуют следующим методам LINQ:

Enumerable.Where(IQueryable<TSource> source, Func<TSource, bool> predicate);
Enumerable.GroupBy(IQueryable<Source> source, Func<TSource, TKey> selector);

So должно быть ясно, что Refl.T1 отправляется туда, где TSource исчезнет в обоих этих вызовах, а Refl.T2 представляет параметр TKey. Классы TX объявляются как таковые:

static class Refl {
  public sealed class T1 { }
  public sealed class T2 { }
  public sealed class T3 { }
  // ... more, if you so desire.
}
]

С тремя классами TX ваш код может идентифицировать методы, содержащие до трех параметров типового типа.

Следующий бит магии - реализовать функцию, выполняющую поиск через GetMethods():

public static MethodInfo GetMethod(this Type t, string name, params Type[] parameters)
{
    foreach (var method in t.GetMethods())
    {
        // easiest case: the name doesn't match!
        if (method.Name != name)
            continue;
        // set a flag here, which will eventually be false if the method isn't a match.
        var correct = true;
        if (method.IsGenericMethodDefinition)
        {
            // map the "private" Type objects which are the type parameters to
            // my public "Tx" classes...
            var d = new Dictionary<Type, Type>();
            var args = method.GetGenericArguments();
            if (args.Length >= 1)
                d[typeof(T1)] = args[0];
            if (args.Length >= 2)
                d[typeof(T2)] = args[1];
            if (args.Length >= 3)
                d[typeof (T3)] = args[2];
            if (args.Length > 3)
                throw new NotSupportedException("Too many type parameters.");

            var p = method.GetParameters();
            for (var i = 0; i < p.Length; i++)
            {
                // Find the Refl.TX classes and replace them with the 
                // actual type parameters.
                var pt = Substitute(parameters[i], d);
                // Then it's a simple equality check on two Type instances.
                if (pt != p[i].ParameterType)
                {
                    correct = false;
                    break;
                }
            }
            if (correct)
                return method;
        }
        else
        {
            var p = method.GetParameters();
            for (var i = 0; i < p.Length; i++)
            {
                var pt = parameters[i];
                if (pt != p[i].ParameterType)
                {
                    correct = false;
                    break;
                }
            }
            if (correct)
                return method;
        }
    }
    return null;
}

Приведенный выше код выполняет основную часть работы - он выполняет итерацию через все методы определенного типа и сравнивает их с заданными типами параметров для поиска. Но подождите! «заменить» функцию? Это хорошая малорекурсивная функция, которая будет искать все дерево типов параметров. В конце концов, тип параметра сам может быть общим типом, который может содержать типы Refl.TX, которые должны быть заменены для параметров «реального» типа которые скрыты от нас.

private static Type Substitute(Type t, IDictionary<Type, Type> env )
{
    // We only really do something if the type 
    // passed in is a (constructed) generic type.
    if (t.IsGenericType)
    {
        var targs = t.GetGenericArguments();
        for(int i = 0; i < targs.Length; i++)
            targs[i] = Substitute(targs[i], env); // recursive call
        t = t.GetGenericTypeDefinition();
        t = t.MakeGenericType(targs);
    }
    // see if the type is in the environment and sub if it is.
    return env.ContainsKey(t) ? env[t] : t;
}
17
задан Mark McDonnell 3 August 2010 в 21:06
поделиться

3 ответа

Поплавки, абсолютное позиционирование элементы, инлайн-блоки, ячейки-таблицы, table-captions и элементы с 'переполнение' кроме 'видимого' (кроме случаев, когда это значение было распространяется на область просмотра) установить новые контексты форматирования блоков.

В контексте форматирования блока каждый левый внешний край коробки касается левого край содержащего блока (для форматирование справа налево, правый край трогать). Это верно даже в наличие поплавков (хотя коробочный линейные боксы могут сжиматься из-за плавает), если бокс не устанавливает новый контекст форматирования блока (в котором случае сама коробка может стать уже за счет поплавков).

Контекст форматирования блока очищает числа с плавающей запятой. Источник: http://www.w3.org/TR/CSS2/visuren.html#block-formatting

10
ответ дан 30 November 2019 в 14:28
поделиться

Ну, кажется, нет «фактического» объяснения того, почему это происходит (не то, что я могу понять в любом случае - например, отрывок спецификации CSS, предоставленный в одном из ответов, просто объяснил, что блок с плавающим содержимым не должен расширяться для переноса). плавающие элементы - это нормально, и это логично, и я полностью это понимаю)

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

Должно быть просто взломать.

Самый полезный ресурс, с которым я столкнулся (или тот, который дал больше деталей - хотя и не столько деталей, сколько мне нужно), был из Quirksmode: http://www.quirksmode.org/css/clearing. html

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

М.

0
ответ дан 30 November 2019 в 14:28
поделиться

Полное объяснение из Модель визуального форматирования, часть 9.2 "Поплавки" спецификации CSS2:

Граница таблицы, заменяемый элемент на уровне блока или элемент в обычном потоке, который устанавливает новый контекст форматирования блока (например, элемент с 'overflow', отличным от 'visible') не должен перекрывать поплавки в том же контексте форматирования блока, что и сам элемент. Если необходимо, реализации должны очистить указанный элемент, поместив его ниже всех предшествующих плавающих элементов, но могут поместить его рядом с такими плавающими элементами, если есть достаточно места. Они могут даже сделать границы указанного элемента более узкими, чем определено в разделе 10.3.3. CSS2 не определяет, когда UA может поместить указанный элемент рядом с поплавком или на сколько указанный элемент может стать более узким.

2
ответ дан 30 November 2019 в 14:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: